OH3 with NGINX Reverse Proxy and Authentication

Doc update submitted. Should bring the docs up to closely match the openhabian config and includes this authorization directive situation.

4 Likes

@ysc might be able to correct me, but the additional add_header block should not be in the location block:

From the nginx docs:

There could be several add_header directives. These directives are inherited from the previous configuration level if and only if there are no add_header directives defined on the current level.

By using add_header in the location block, you remove the headers relating to CORS and strict transport security:

The openHABian template should be:

##################################
# openHABian NGINX Configuration #
##################################

## Redirection
#REDIR server {
#REDIR   listen                          80;
#REDIR   server_name                     DOMAINNAME;
#REDIR   return 301                      https://$server_name$request_uri;
#REDIR }

## Reverse Proxy to openHAB
server {
    listen                          80;
#SSL   listen                          443 ssl;
    server_name                     DOMAINNAME;
#SSL   add_header                      Strict-Transport-Security "max-age=31536000; includeSubDomains";

    # Cross-Origin Resource Sharing.
    add_header 'Access-Control-Allow-Origin' '*' always; # make sure that also a 400 response works
    add_header 'Access-Control-Allow_Credentials' 'true' always;
    add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range' always;
    add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH' always;
#AUTH   add_header Set-Cookie X-OPENHAB-AUTH-HEADER=1;

## Secure Certificate Locations
#CERT   ssl_certificate                 CERTPATH;
#CERT   ssl_certificate_key             KEYPATH;

    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_read_timeout 3600;
#AUTH        proxy_set_header Authorization "";

## Password Protection
#OH2AUTH       auth_basic                              "Username and Password Required";
#OH2AUTH       auth_basic_user_file                    /etc/nginx/.htpasswd;
    }

## Let's Encrypt webroot location
#WEBROOT   location /.well-known/acme-challenge/ {
#WEBROOT       root                                    /var/www/DOMAINNAME;
#WEBROOT   }
}

# vim: filetype=conf

The script also implies that the htpasswd, is used for an OH2 instance only, this isn’t necessarily the case and htpasswd could be used to provide basic auth on OH3:

@Benjy looks like you’re right - those 2 lines add_header and proxy_set_header to make the whole thing work should be added with their existing siblings.

Agreed as well.

2 Likes

PR updated to reflect that.

Thanks once again @rlkoshak, once again excactly the info I was looking for! I run opnsense, but exactly the same config works there. I prefer to have it the same way. Just wanted to leave a keyword trace here if someone is searching authorization help with oh3 via haproxy using opnsense.

Nah, too hasty. It probably had some stuff in cache. Now it’s again in the loop of asking password if I try logging in from OH3 login button.

I have this in my opnsense haproxy.cfg:

    # ACTION: require_auth
    http-request auth realm fooo unless acl_5afc4930790c77.74502605
    # ACTION: add_header_openhab_cookie
    # NOTE: actions with no ACLs/conditions will always match
    http-request add-header Set-Cookie XOPENHAB-AUTH-HEADER=1;path=/;Secure 
    # ACTION: remove_header_auth
    # NOTE: actions with no ACLs/conditions will always match
    http-request del-header Authorization 
    http-reuse never
    server OpenHAB fedora-iot:8083 check inter 2s

So https gets terminated at opnsense after haproxy does basic auth. Then I see openhab screen just nicely. I then click on left bottom corner login button, which brings the auth dialog. After inserting creds and pressing ok it just brings back the dialog. Nothing in the logs.

That add-header is actually three header entries. Maybe opnSense won’t let you combine them all on one line like that. I saw that same behavior until I got the path and Secure parts reset in the header too.

This is how it creates the cookie, looking from firefox, I’d assume this is expected:

Screenshot from 2021-02-15 21-59-23

Screenshot from 2021-02-15 21-58-59

The only thing that bothers me there is that it sets dot in front of the domain. But I suppose it’s right.

I’m well outside my depth but that Secure: true doesn’t look right. The Secure with nothing after it should probably have removed that header entry entirely.

I don’t have that in my cookie.

If I drop the word Secure from the haproxy line, it shows Secure=false in firefox.

There is something odd, as if I keep hammering the login box, there is nothing in the logs. I don’t know if that’s intentional to avoid DDOS, or is there some problem for the login dialog script in firefox getting back to openhab via haproxy.

Anyhow, if anyone has ideas why it behaves like this, please help.

the firefox console pukes this out while trying to login:

Initializing state tracking store proxy app.js:37:1835
Uncaught (in promise) undefined
Uncaught (in promise) undefined
Using passed credentials app.js:7:121713
Uncaught (in promise) undefined app.js:32:436561
    loadData https://o.mydomain.com/js/app.js:32
Uncaught (in promise) undefined
Uncaught (in promise) undefined

There is a graduated backoff time after a failed login. I don’t remember what the time is but I remember there being a discussion about how it could be a mechanism for a denial of service. I don’t know if that ever changed.

Beyond that I’m no expert in this stuff. It worked for me as described above and I don’t know HAProxy well enough to begin to diagnose this problem.

I’ll move the haproxy config discussion to it’s own topic, as this is not related to NGINX: OH3 behind haproxy. Let’s continue HAproxy topic there.

Hi,

I am trying to externalize my instance using Nginx. I have a few question because the more I read the more mixed up it gets…

First of all what is the best practice to externalize OH3?
Do I need to turn on / off the Api Security → Basic Auth setting?
If I am only using OH3 auth and do not use basic auth in Nginx, is there a way to disable Anonymous auth?

I followed the Nginx setup document and now I have basic auth enabled. Still without entering the basic auth creds the page loads:

I am also trying to use the iOS app. I know that currently it cannot render MainUI however I could still utilize Shortcuts and some other stuff so it would be good to be able to use it remotely. What do I need in order to be able to use the app? Because I set the username and password but it is not working. Which auth methods the app is compatible with?

Use myopenhab.org. Failing that using a self hosted version of the openHAB Cloud server. Only after failing that consider NGINX.

Don’t do that. openHAB auth only protects certain administration function. It does not protect the whole installation. As a result, anyone on the internet will be able to access your Pages and send commands to your Items without any authentication/authorization. You need to add additional auth/auth using NGINX. That’s sort of the point.

I can’t speak to the iOS app. In the android app you can set up basic auth credentials for the remote connection URL. I assume that the iOS app works the same. But that means you have to implement basic auth in your NGINX configuration.

As a general rule of thumb, if you have to ask these sorts of questions I strongly recommend against punching a hole through your firewall like this, even with a reverse proxy. You can get it to work but you most likely do not have the knowledge nor the skills to continuously monitor it and identify and mitigate the attacks on your server when they occur.

There is some evidence here on the forum that there are attack bots that are openHAB aware and will recognize your server and perform automated attacks.

It is more about that I read the document I checked the threads and it was simply not clear how to proceed. Especially because some of the infromation is still only mentioning OH2 and since it’s been 3 years I used OH I’m a bit disconnected.

Anyway I am not really worried about attacks and hosting my own solution I have Azure Front Door and WAF around my services. That said if the generic recommendation is to use it with myopenhab.org / self-hosted OH cloud server then I’ll probably go with one of those.

It would be still good to understand why the site is opening when I have the basic auth set. I would assume that the site should be only loading once the auth occurs. For the iOS app I read several threads all mixed information, so if anyone has up to date experience with it I would love some input.

Thanks!

As i said, openHAB’s auth only protects the administration parts of the REST API. It doesn’t protect the user portions (e.g. your Pages). It’s not a complete security protection mechanism. You would have to have basic auth configured in your NGINX reverse proxy to protect those with usename and password too. Of course then to get to the admin parts of the OH you’d have to authenticate twice, once with NGINX and again with openHAB.

As I said I have Nginx basic auth configured. My issue was that even that set some of the pages loaded (I was not able to perform any actions without typing the u/pw in).

I had time this morning to investigate further it seems that the problem was with my CDN caching the content. I turned it off and now it is properly asking for the auth without presenting any pages (cached content). So this part is solved…

…Still the iOS app is not working.

Is this still true? Because if it is then I would need to stick to client certs if I would keep the Nginx approach.

Probably better to continue here.

Hello,

Thank you all for the configuration tips !

I was wondering if there is a way to directly pass the username from the proxy to openhab ? as after all the user is already authenticated by the proxy !

Something like that (example with apache used as a proxy authenticating the user) that would make openhab understand that there is no need to authenticate furthermore but to proceed with the request for REMOTE_USER :

RequestHeader set X-Remote-User expr=%{REMOTE_USER}

It may (so I’d like to get the variable name) or may not be implemented (so I’d eventually request it) ?

1 Like