Can't change 'X-Frame-Options' nginx reverse-proxy

Hello everyone

I use Metabase .jar version / ubuntu 20.04 with Nginx reverse-proxy
And I wanna use my Metabase in iFrame
I have already found an issue with 'X-Frame-Options' due to set 'deny' so an easy way to solve it was to add a header add_header X-Frame-Options "ALLOW-ALL"; in my Nginx reverse-proxy

But it didn't solve my issue. Right now I have conflicting values ('DENY, ALLOWALL'). Falling back to 'deny' in browser conclose

Refused to display in a frame because it set multiple 'X-Frame-Options' headers with conflicting values ('DENY, ALLOWALL'). Falling back to 'deny'

It seems like Nginx can't rewrite 'deny' value

How can I fix it?

My nginx config

location / {
proxy_pass http://mydomain.com:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto https;
add_header X-Frame-Options ALLOWALL;
}

image

Hi @Dmitrii
Because you need to block the header coming from Metabase:
https://serverfault.com/questions/928912/how-do-i-remove-a-server-added-header-from-proxied-location/982013

thanks for reply

How I saw in your link I trying to remove 'X-Frame-Options' header and add it with "ALLOWALL" value

proxy_hide_header X-Frame-Options;
add_header X-Frame-Options "ALLOWALL";

my full nginx now:

    location / {
            proxy_pass http://matabase:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Host $server_name;
            proxy_set_header X-Forwarded-Proto https;
            proxy_hide_header X-Frame-Options;
            add_header X-Frame-Options "ALLOWALL";
    }

so iFrame works right now, but there is a new problem it's don't show the top navigation panel

Uncaught TypeError: Cannot read property 'contains' of undefined
    at t.isFitViewportMode (app-main.bundle.js?1e6ba1eae4be22e31f2b:5)
    at app-main.bundle.js?1e6ba1eae4be22e31f2b:5

Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('<URL>') does not match the recipient window's origin ('<URL>').

@Dmitrii postMessage are only available on the Enterprise Edition, so you can ignore those errors.

@flamber

there is no nav panel

in iFrame

without iFrame

@Dmitrii Please post "Diagnostic Info" from Admin > Troubleshooting.

please see

{
  "browser-info": {
    "language": "ru-RU",
    "platform": "Win32",
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36",
    "vendor": "Google Inc."
  },
  "system-info": {
    "file.encoding": "UTF-8",
    "java.runtime.name": "OpenJDK Runtime Environment",
    "java.runtime.version": "14.0.2+12-Ubuntu-120.04",
    "java.vendor": "Private Build",
    "java.vendor.url": "Unknown",
    "java.version": "14.0.2",
    "java.vm.name": "OpenJDK 64-Bit Server VM",
    "java.vm.version": "14.0.2+12-Ubuntu-120.04",
    "os.name": "Linux",
    "os.version": "5.4.0-72-generic",
    "user.language": "en",
    "user.timezone": "Etc/UTC"
  },
  "metabase-info": {
    "databases": [
      "h2",
      "mysql"
    ],
    "hosting-env": "unknown",
    "application-database": "h2",
    "application-database-details": {
      "database": {
        "name": "H2",
        "version": "1.4.197 (2018-03-18)"
      },
      "jdbc-driver": {
        "name": "H2 JDBC Driver",
        "version": "1.4.197 (2018-03-18)"
      }
    },
    "run-mode": "prod",
    "version": {
      "date": "2020-07-31",
      "tag": "v0.36.2",
      "branch": "release-0.36.x",
      "hash": "13f0225"
    },
    "settings": {
      "report-timezone": null
    }
  }
}

@Dmitrii

  1. Latest release is 0.39.1
    https://github.com/metabase/metabase/releases/latest
  2. You should migrate away from H2 if you're using Metabase in production:
    https://www.metabase.com/docs/latest/operations-guide/migrating-from-h2.html
  3. Use the latest LTS version of Java:
    https://www.metabase.com/docs/latest/operations-guide/java-versions.html
  4. The header navigation is not shown, when doing a Full App Embedding:
    https://www.metabase.com/docs/latest/enterprise-guide/full-app-embedding.html

thanks for your advice
I will do 1,2,3 steps for improving my Metabase

about 4.
can you please give me advice if nav bar now shown that how I can use those options?

@Dmitrii You would have to not embed Metabase in an iframe. We are working on making the navigation bar customizable, but that will likely only be provided in the Enterprise Edition.

so if I put my self-hosted Metabase in iFrame then i just lost the top navigation bar and can't return it anymore except using Metabase without iFrame?

sounds strange how working on fullapp iFrame to lost the top nav

anyway thank you very much for helping me

@Dmitrii Because this allows Metabase to be integrated into your own apps, where you can control where people can go with postMessage - like I said, only available in the Enterprise Edition:
https://www.metabase.com/docs/latest/enterprise-guide/full-app-embedding.html

thanks

I decided to improve my Metabase following your suggestions above.
So I just install a new docker-compose Metabase https://github.com/Cambalab/metabase-compose

And I faced with a new issue with shown Metabase from iFrame now it is a new error in console

Refused to frame 'https://reports.domain.com/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'none'".

my Nginx reverse-proxy looks

location / {
    proxy_pass http://10.50.0.8:3000;

    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $server_name;
    proxy_set_header X-Forwarded-Proto https;
    proxy_hide_header X-Frame-Options;
    add_header X-Frame-Options "ALLOWALL-FROM cloud.domain.com";
    add_header Content-Security-Policy "frame-ancestors cloud.domain.com";
}

Maybe you faced with it somewhere?

also my Metabase Diagnostic Info:

{
  "browser-info": {
    "language": "ru-RU",
    "platform": "Win32",
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36",
    "vendor": "Google Inc."
  },
  "system-info": {
    "file.encoding": "UTF-8",
    "java.runtime.name": "OpenJDK Runtime Environment",
    "java.runtime.version": "11.0.11+9",
    "java.vendor": "AdoptOpenJDK",
    "java.vendor.url": "https://adoptopenjdk.net/",
    "java.version": "11.0.11",
    "java.vm.name": "OpenJDK 64-Bit Server VM",
    "java.vm.version": "11.0.11+9",
    "os.name": "Linux",
    "os.version": "5.4.0-73-generic",
    "user.language": "en",
    "user.timezone": "America/Buenos_Aires"
  },
  "metabase-info": {
    "databases": [
      "h2"
    ],
    "hosting-env": "unknown",
    "application-database": "mysql",
    "application-database-details": {
      "database": {
        "name": "MySQL",
        "version": "5.7.34"
      },
      "jdbc-driver": {
        "name": "MariaDB Connector/J",
        "version": "2.6.2"
      }
    },
    "run-mode": "prod",
    "version": {
      "date": "2021-04-27",
      "tag": "v0.39.1",
      "branch": "release-x.39.x",
      "hash": "6beba48"
    },
    "settings": {
      "report-timezone": null
    }
  }
}

@Dmitrii X-Frame-Options is a legacy header that is only respected by Internet Explorer. All other browsers uses CSP headers. You'll need to replace the CSP header, not just add a subsection of that.

thanks

I just did it and it works

proxy_hide_header Content-Security-Policy;
add_header Content-Security-Policy "frame-ancestors cloud.domain.com";

@Dmitrii You should look at the current CSP header and modify it - the way you're doing now will remove all the security and only add frame-ancestors security.

if I just add add_header Content-Security-Policy "frame-ancestors" it doesn't work I'm not sure how can I modify it correctly
Can I use proxy_hide_header Content-Security-Policy "frame-ancestors": ?

@Dmitrii No, that's not how Nginx works. It hides the entire header, not parts of it:
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_hide_header
Copy the entire CSP header and modify it - or don't, and just run with less security.