Docker, OAuth2_proxy, Traefik, and HA New Auth System - Can they all work together?

My question essentially boils down to this - is it possible to make oauth2 via a Google login work with Home Assistant please?

I would like to access my HA environment from the internet, but would prefer extra levels of authentication security. I don’t want to just expose the native login screen by itself, be it either HA (using the latest auth system in 0.77.3) or any other web-based app I have running on my internal network.

To accomplish this I have been using Bitly’s OAuth2_proxy as a Docker container, which essentially lets me use my Google Account to securely log in using two-factor authentication before then being passed to internal web app logins.

This works great for all my other web-based apps running in docker containers, only Home Assistant (and Portainer) won’t work with oauth2_proxy.

Does anyone know why please? Has anyone with a similar config managed to get this to work?

The detail behind my setup is as follows:

I have a docker container that runs Traefik as a reverse proxy for all my internal web apps (docker and non-docker) instead of using nginx. The beauty of Traefik is that it automatically handles the Let’s Encrypt https certification and automatic redirection to any new containers you set up. See here for setting up docker, and here for adding traefik.

I then wanted to add extra login security by using Oauth2, and found this guide useful for explaining how to integrate it with Traefik. However it wasn’t all that clear how to set up Google’s OAuth with a single Client ID, so my post here should help clarify things.

As you can see on that thread, the author suggests it’s a websocket issue, but based on this blog here it looks like we should be able to pass a custom header to HA via the proxy because it essentially says HA should work behind a proxy. If however it is ultimately down to websockets, is there any way around this? Are the devs aware of this? Is there any other way of using OAuth via Google for extra security?

As seen in the docker-compose code below, I have attempted to pass a custom header using traefik labels with no luck. If anyone can offer any insights or ideas to help make this work, I would be very much grateful.

docker-compose.yml

version: "3.6"
services:
  traefik:
    hostname: traefik
    image: traefik:latest
    container_name: traefik
    restart: always
    domainname: ${DOMAINNAME}
    networks:
      - default
      - traefik_proxy
    ports:
      - "80:80"
      - "443:443"
      - "9011:8080"
    environment:
      - CLOUDFLARE_EMAIL=${CLOUDFLARE_EMAIL}
      - CLOUDFLARE_API_KEY=${CLOUDFLARE_API_KEY}
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ${USERDIR}/docker/traefik:/etc/traefik
      - ${USERDIR}/docker/shared:/shared

  hass_proxy:
    image: a5huynh/oauth2_proxy
    env_file: ${USERDIR}/docker/env/master.env
    hostname: hass_proxy
    container_name: hass_proxy
    restart: always
    networks:
      - traefik_proxy
    labels:
      - traefik.enable=true
      - traefik.backend=hass_proxy
      - traefik.frontend.rule=Host:hass.${DOMAINNAME}
      - traefik.docker.network=traefik_proxy
      - traefik.port=4180
      - traefik.frontend.headers.SSLRedirect=true
      - traefik.frontend.headers.STSSeconds=315360000
      - traefik.frontend.headers.browserXSSFilter=true
      - traefik.frontend.headers.contentTypeNosniff=true
      - traefik.frontend.headers.forceSTSHeader=true
      - traefik.frontend.headers.SSLHost=${DOMAINNAME}
      - traefik.frontend.headers.STSIncludeSubdomains=true
      - traefik.frontend.headers.STSPreload=true
      - traefik.frontend.headers.frameDeny=true
      - traefik.frontend.headers.customrequestheaders=x-ha-access:my_api_pass
    volumes:
      - ${USERDIR}/docker/oauth_proxy/authenticated-emails.txt:/authenticated-emails.txt
    command: |
      -cookie-secure=false
      -upstream=http://my_internal_HA_ip:8123
      -redirect-url=https://hass.${DOMAINNAME}
      -http-address=http://0.0.0.0:4180
      -provider=google
      -authenticated-emails-file=/authenticated-emails.txt
      -pass-host-header=true
      -pass-user-headers=true

If anyone would still like to access HA behind a Traefik reverse proxy without Oauth, the following rules.toml file will redirect to wherever you have HA installed (see here)

rules.toml

[backends]
  [backends.hass]
    [backends.hass.servers.server2]
    url = "http://my_internal_ha_ip:8123"

[frontends]
  [frontends.hass]
    backend = "hass"
    passHostHeader = true
    [frontends.hass.routes.routes1]
      rule = "Host:hass.example.com"

Hope all that makes sense - reading those guides will help…

I’m not sure why you don’t want to expose the native login screen. If you expose HA behind Traefik (without OAuth2) and then use HA’s built in auth (with user/pass and two-factor authentication), that is very secure. And arguably even more so because you are not trusting a third-party to “vouch” for you. You can also set HA to ban an IP address after repeated failed login attempts.

This is exactly how I have it set up.

Before HA’s new auth system, I tried to get it set up through OAuth, but never got it to work either. So, I just use a really long randomly generated password and exposed the main login page.

Hi,
Did you make any progress with this?

I’m about to redo my hass setup using traefik, docker, etc.

Thanks,
RJ

Not sure there is any progress to be made.

Expose HA through Traefik (encrypted on port 443), turn on two-factor auth, and you’re secure.

If you expose HA behind Traefik (without OAuth2) and then use HA’s built in auth (with user/pass and two-factor authentication), that is very secure.

Is this your opinion?! In general, these technologies are secure but who has checked the implementation in Home Assistant?!