OH3 with NGINX Reverse Proxy and Authentication

I’ve been running OH2 using a NGINX reverse proxy with authentication. It is setup very similar to what is documented at https://www.openhab.org/docs/installation/security.html#running-openhab-behind-a-reverse-proxy and https://www.openhab.org/docs/installation/security.html#authentication-with-nginx.

Accessing both https://host/basicui/app and https://host/ are working as expected. But when I log into openhab using the login screen, the login dialog from NGINX pops up, and it no longer lets me log in with the correct username and password.

Has anybody been able to get OH3 working with NGINX reverse proxy and authentication for the openhab adminstration? The only way I can access OH3 administration is via http://host:8080/.

1 Like

I think I see what’s going on, when I authenticate with NGINX it adds in the header:

authorization: Basic ...

And after I log into OH3, the header becomes:

authorization: Bearer ...

So we have both nginx and OH3 using the same header. There isn’t a problem until you are authenticated with OH3.

There has been a lengthy discussion about the usage of oauth.
It looks like it will be possible to use BasicAuth again with the next milestone

I looked at the PR, I don’t see how this would work with a reverse proxy where NGINX requires authentication to access all requests, and OH3 requires separate authentication for administrative access.

If you use the same user/pw combination for both, it’ll work because the basic auth header is the same

1 Like

This situation has been foreseen - and this has nothing to do with the authorization flow - the problem as you correctly identified is that NGINX and openHAB share the HTTP Authorization header and that leads to conflicts.

There’s a way to make the openHAB UI use a different header (X-OPENHAB-TOKEN) in those cases, which is to make NGINX set a cookie accessible to JavaScript that will tell it to use a different header to transmit its own authorization credentials, the cookie’s name is X-OPENHAB-AUTH-HEADER, you can set to any value you want as long as it is present. I know that this needs proper documentation but we’ll get there.

So anyway in NGINX putting something like this in your ‘location’ block should work:

add_header Set-Cookie X-OPENHAB-AUTH-HEADER=true;

See also https://github.com/openhab/openhab-cloud/pull/311 for openHAB Cloud.

2 Likes

Thanks @ysc, I got it working but I’m seeing multiple X-OPENHAB-AUTH-HEADER in the request header:

cookie: X-OPENHAB-AUTH-HEADER=1; X-OPENHAB-AUTH-HEADER=1

Do you know what could be causing this?

Sorry @ranielsen, no clue.

Will an NGINX with this header continue to work for OH2.X ?
Would it hence make sense to add that to the default NGINX configuration in openHABian ?

I don’t see any reason it won’t work. Yes it would make sense to add to openHABian.

OH3 now supports basic authentication, you’ll need to add the following to make it work:

add_header Set-Cookie X-OPENHAB-AUTH-HEADER=1;
proxy_set_header Authorization "";

If you don’t add the second line, you need to change the api security settings to allow basic authentication.

7 Likes

I was just coming here to add this, thanks! :wink:

Note: from a security perspective, that second line is rather important to include when you’re doing authorization at the reverse proxy level, it ensures the header containing the credentials meant to be exclusively for the proxy, are filtered out and not transmitted (likely in clear text) in the internal network.

Is there a link to the authentication model for OH3 and X-OPENHAB-AUTH-HEADER? A quick search here doesn’t match anything. I’m confused about the authentication support in OH3. I use a webbrowser that doesn’t support Basic Authentication and it would great if OH3 kept a cookie or supported Oauth.

If you use Traefik as reverse proxy, these lines do the job for basic auth. Append them to the OH service under “labels” in your docker-compose file.

      - traefik.http.routers.openhab.middlewares=auth,oh
      - traefik.http.middlewares.auth.basicauth.users=[generated by htpasswd]
      - traefik.http.middlewares.auth.basicauth.removeHeader=true
      - traefik.http.middlewares.oh.headers.customresponseheaders.Set-Cookie=X-OPENHAB-AUTH-HEADER=1
1 Like

See the current template at https://github.com/openhab/openhabian/edit/master/includes/nginx.conf.
Should I just add another add_header (i.e. line 24) or does it have to be inside the ‘location’ block as @ysc said ? Would I even need another such block ?

Hello,
I’m trying to make it work, but even after adding this lines to nginx config file I still get “502 Bad Gateway” response.
Any ideas?

Thanks @ranielsen :slight_smile:
would someone happen to know the equivalent for apache?
edit: a bit of digging late, i found a working config!

Header set Set-Cookie "X-OPENHAB-AUTH-HEADER=1"
    ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse http://127.0.0.1:8080/ /
  	Header add Authorization ""
  	RequestHeader set Authorization ""

This is my nginx config:

#################################
# openHABian NGINX Confiuration #
#################################

## Reverse Proxy to openHAB
server {
    listen                          1234;
    server_name                     xxxxxxxxx;
    add_header Set-Cookie X-OPENHAB-AUTH-HEADER=1;
    location / {
        proxy_pass                              http://localhost:8080;
        proxy_set_header Host                   $http_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-Proto      $scheme;
        proxy_set_header Authorization "";
       auth_basic                              "Username and Password Required";
       auth_basic_user_file                    /etc/nginx/.htpasswd;
    }


}

And OPENHAB 3 settings:
Zrzut ekranu 2020-12-7 o 10.02.05

So if I have proxy_set_header Authorization ""; added to nginx config I can turn off “Allow Basic Authentication” in OH settings?

When now OH3 uses API Tokens does the lines need to be still in nginx conf?

auth_basic                              "Username and Password Required";
auth_basic_user_file                    /etc/nginx/.htpasswd;

What is the best way now to secure connections to OPENHAB 3.0?

did you or anyone figure out?

as far as I checked:

OH2 with nginx with Basic Auth - when I open Paper UI or Basic UI I needed to enter login and password same as in /etc/nginx/.htpasswd

on same nginx conf but on OH3 - when I open Openhab Main UI or Basic UI I needed to enter login and password set for administrator from Main UI

now I added SSL to nginx and on OH3 - when I open Main UI or Basic UI I enter login and pass from .htpasswd and also in Main UI addidtional login and pass for administrator.

here is my new nginx config:

#################################
# openHABian NGINX Confiuration #
#################################

## Reverse Proxy to openHAB
server {
        listen                          80;
        server_name                     xxxxxxxx;
        return 301                      https://$server_name$request_uri;
}

server {
        listen                          443 ssl;
        server_name                     xxxxxxxx;
        ssl_certificate                 /etc/ssl/openhab.crt;
        ssl_certificate_key             /etc/ssl/openhab.key;
        add_header Set-Cookie X-OPENHAB-AUTH-HEADER=1;
    location / {
        proxy_pass                              http://localhost:8080;
        proxy_set_header Host                   $http_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-Proto      $scheme;
        proxy_set_header Upgrade                $http_upgrade;
        proxy_set_header Authorization "";
        satisfy                                 any;
        allow                                   192.168.0.0/24;
        allow                                   127.0.0.1;
        deny                                    all;
        auth_basic                              "Username and Password Required";
        auth_basic_user_file                    /etc/nginx/.htpasswd;
    }
        location /grafana/ {
                proxy_pass                            http://localhost:3000/;
                proxy_set_header Host                 $http_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-Proto    "https";
                auth_basic                            "Unauthorised access prohibited";
                auth_basic_user_file                  /etc/nginx/.htpasswd;
        }

    location /frontail/ {
        proxy_pass                              http://localhost:9001;
        proxy_set_header Host                   $http_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-Proto      $scheme;
        proxy_set_header Connection             "upgrade";
        proxy_set_header Upgrade                $http_upgrade;
    }

}
1 Like