netbird icon indicating copy to clipboard operation
netbird copied to clipboard

OIDC: wrong host for .well-known/openid-configuration

Open Cheezzhead opened this issue 1 year ago • 3 comments
trafficstars

Describe the problem

I get an Error: Unauthenticated message upon opening the dashboard homepage. Checking the browser's development console, it is attempting to fetch the OIDC configuration from http://localhost/.well-known/openid-configuration which is obviously wrong. I can't find the (environment?) variable to change this.

Additionally (not sure if related), but the setup script generates an openid-configuration.json file which is never used in the generated compose file. Is this intentional?

To Reproduce

Relevant part from docker-compose.yml:

services:
  dashboard:
    image: netbirdio/dashboard:latest
    # ...
    environment:
      # ...
      # OIDC
      - AUTH_AUDIENCE=netbird
      - AUTH_CLIENT_ID=clientId
      - AUTH_CLIENT_SECRET=clientSecret
      - AUTH_AUTHORITY=https://auth.domain.tld
      - USE_AUTH0=false
      - AUTH_SUPPORTED_SCOPES=openid profile email offline_access api groups
      - NETBIRD_TOKEN_SOURCE=accessToken
      # ...

  management:
    image: netbirdio/management:latest
    // ...
    ports:
      - 33073:443
    command: [
      "--port", "443",
      "--log-file", "console",
      "--log-level", "info",
      "--disable-anonymous-metrics=false",
      "--single-account-mode-domain=net.doman.tld",
      "--dns-domain=netbird.selfhosted",
      # Only if dashboard doesn't exist/enable letsencrypt
      "--letsencrypt-domain", "net.domain.tld", 
    ]
    volumes:
      - netbird-mgmt:/var/lib/netbird
      - letsencrypt:/etc/letsencrypt:ro
      - ./management.json:/etc/netbird/management.json

management.json:

{
    "Stuns": [
      {
        "Proto": "udp",
        "URI": "stun:net.domain.tld:3478",
        "Username": "",
        "Password": null
      }
    ],
    "TURNConfig": {
      "Turns": [
        {
          "Proto": "udp",
          "URI": "turn:net.domain.tld:3478",
          "Username": "self",
          "Password": "ZTgDOSevQghQDn6ZMgVYKld4vB0hXQ5dZ23cYM5pG0M"
        }
      ],
      "CredentialsTTL": "12h",
      "Secret": "secret",
      "TimeBasedCredentials": false
    },
    "Signal": {
      "Proto": "https",
      "URI": "net.domain.tld:10000",
      "Username": "",
      "Password": null
    },
    "ReverseProxy": {
      "TrustedHTTPProxies": [],
      "TrustedHTTPProxiesCount": 0,
      "TrustedPeers": [
        "0.0.0.0/0"
      ]
    },
    "Datadir": "",
    "DataStoreEncryptionKey": "",
    "StoreConfig": {
      "Engine": "sqlite"
    },
    "HttpConfig": {
      "Address": "0.0.0.0:33073",
      "AuthIssuer": "https://auth.domain.tld",
      "AuthAudience": "netbird",
      "AuthKeysLocation": "https://auth.domain.tld/jwks.json",
      "AuthUserIDClaim": "preferred_username",
      "CertFile": "",
      "CertKey": "",
      "IdpSignKeyRefreshEnabled": false,
      "OIDCConfigEndpoint": "https://auth.domain.tld/.well-known/openid-configuration"
    },
    "IdpManagerConfig": {
      "ManagerType": "",
      "ClientConfig": {
        "Issuer": "https://auth.domain.tld",
        "TokenEndpoint": "https://auth.domain.tld/api/oidc/token",
        "ClientID": "",
        "ClientSecret": "",
        "GrantType": "client_credentials"
      },
      "ExtraConfig": {},
      "Auth0ClientCredentials": null,
      "AzureClientCredentials": null,
      "KeycloakClientCredentials": null,
      "ZitadelClientCredentials": null
    },
    "DeviceAuthorizationFlow": {
      "Provider": "none",
      "ProviderConfig": {
        "Audience": "netbird",
        "AuthorizationEndpoint": "",
        "Domain": "",
        "ClientID": "",
        "ClientSecret": "",
        "TokenEndpoint": "https://auth.domain.tld/api/oidc/token",
        "DeviceAuthEndpoint": "null",
        "Scope": "openid",
        "UseIDToken": false,
        "RedirectURLs": null
      }
    },
    "PKCEAuthorizationFlow": {
      "ProviderConfig": {
        "Audience": "netbird",
        "ClientID": "mMZH_ychgEKCMF73v0gFvy1~aSL7uCzS6oBJu8qVJrik4Kr.g_zQtonWEioCXRl746yFO.eC",
        "ClientSecret": "G1wY.vEQTCrMaHuPhnhCzR~Vc~LONL_Y.3UNBRRR5sy-vpgd36xSjRPetNrApOEe3i~p5bNg",
        "Domain": "",
        "AuthorizationEndpoint": "https://auth.domain.tld/api/oidc/authorization",
        "TokenEndpoint": "https://auth.domain.tld/api/oidc/token",
        "Scope": "openid profile email offline_access api groups",
        "RedirectURLs": [
          "http://localhost:53000"
        ],
        "UseIDToken": false
      }
    }
  }

Expected behavior

The configuration should be retrieved from https://auth.domain.tld/.well-known/oidc-configuration.

Are you using NetBird Cloud?

Self-hosted

NetBird version

0.28.7

Cheezzhead avatar Aug 17 '24 18:08 Cheezzhead

it should be in your management.json https://<your.domain.tld>/application/o/netbird/.well-known/openid-configuration",

the mangement.json itself is mounted as a volume in the docker-compose.yml in the management service

collse avatar Aug 18 '24 09:08 collse

Actually I have the similar issue. I am using Zitadel - I was wondering what is the use of below which is setup in the management.json . I am using zitadel and I am not using this redirect URL. Even if I setup this up, where would this point to since myzitadel server is seperate from say netbird server?

        "RedirectURLs": [
          "http://localhost:53000"

manju-rn avatar Aug 18 '24 16:08 manju-rn

it should be in your management.json https://<your.domain.tld>/application/o/netbird/.well-known/openid-configuration",

the mangement.json itself is mounted as a volume in the docker-compose.yml in the management service

Yes, I modified my original post to include the netbird management service config. the management.json is indeed mounted as a volume, but I'm still getting the wrong redirect localhost.

The only property in management.json that would seemingly be relevant to this is OIDCConfigEndpoint, which in my setup is definitely pointing towards the right domain, and changing that doesn't seem to do anything. I don't really see what else would/could be responsible for this, but maybe you can point me in the right direction.

@manju-rn I believe that destination is for OIDC device authorization flow (Specifically PKCE flow), which I'm not well-versed about but should be localhost in most cases. The port is specified in netbird's provided setup.env script:

# -------------------------------------------
# OIDC PKCE Authorization Flow
# -------------------------------------------
# Comma separated port numbers. if already in use, PKCE flow will choose an available port from the list as an alternative
# eg. 53000,54000
NETBIRD_AUTH_PKCE_REDIRECT_URL_PORTS="53000"

Cheezzhead avatar Aug 19 '24 08:08 Cheezzhead

Facing the same issue

sabya-oneassure avatar Sep 09 '24 10:09 sabya-oneassure

Facing the same issue

wiiun avatar Sep 20 '24 04:09 wiiun

after finishing all required setups and run docker compose logs management I got :

  • INFO [context: SYSTEM] management/cmd/management.go:497: loading OIDC configuration from the provided IDP configuration endpoint https://authentik.mydomain.com/application/o/netbird/.well-known/openid-configuration
  • Error: failed reading provided config file: /etc/netbird/management.json: OIDC configuration request returned status 403

ennbou avatar Sep 25 '24 00:09 ennbou

I tried using curl to get the JSON response directly from my local terminal, and it worked perfectly. However, on my VPS, it didn't work due to Cloudflare security. The HTTP request worked in the browser but not with curl. I fixed the issue by whitelisting my VPS's IPv4/IPv6 in Cloudflare's WAF.

ennbou avatar Sep 25 '24 19:09 ennbou

Sorry to bump, stuck on same thing any new ?

....

  - NGINX_SSL_PORT=443

solve it forme:D

ekozan avatar Jan 05 '25 10:01 ekozan

I did try to set up the self hosted compose stack with auth0 and actually forgot to perform step 5 which sets up the machine to machine application https://docs.netbird.io/selfhosted/identity-providers#step-5-create-and-configuire-machine-to-machine-application

Especially watch out for the quoted list of changed lines in setup.env at the end of that list, there are some changes that weren't mentioned in the guide before.

Once I completely restarted everything (with removing the created volumes docker-compose down --volumes, and re-running ./configure) everything came up.

Hope this helps.

brandtjo avatar Jan 25 '25 19:01 brandtjo

Hello @Cheezzhead,

We're currently reviewing our open issues and would like to verify if this problem still exists in the latest NetBird version.

Could you please confirm if the issue is still there?

We may close this issue temporarily if we don't hear back from you within 2 weeks, but feel free to reopen it with updated information.

Thanks for your contribution to improving the project!

nazarewk avatar Apr 28 '25 15:04 nazarewk

Im encountering the same issue. Running netbird v0.44.0 using authentik. Netbird tries to fetch http://localhost/.well-known/openid-configuration when accessing the webpage.

Johgaaa avatar May 19 '25 16:05 Johgaaa

same issue using keycloak all latest version at 28.05.25 v [0.45.1]

Dofamin avatar May 28 '25 18:05 Dofamin

Also experiencing this issue, tried authentik and zitadel, using netbird v0.46.0. According to the logs, the management service gets its configuration from the correct endpoint (https://auth.domain.com/.well-known/openid-configuration) and is also able to log in to the service account to fetch users. The dashboard however always tries to get its openid configuration from http://localhost/.well-known/openid-configuration. Please reopen this issue.

LennartStoehr avatar Jun 16 '25 16:06 LennartStoehr

i'm also facing this issue using auth0 - v0.40.0

trevorsargent avatar Jul 04 '25 02:07 trevorsargent

I'm also facing the same issue with netbird v0.49.0 and keycloak v26.2.5.

I've hacked around it by configuring nginx to proxy-pass the request to the desired location, something like:

http {
  server {
    server_name auth.mydomain.org;
    # ...
    location /.well-known/openid-configuration {
      # ...
      proxy_pass https://auth.mydomain.org/realms/netbird/.well-known/openid-configuration;
    }
  }
}

arminfro avatar Jul 23 '25 10:07 arminfro

@arminfro sounds like something $NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT should handle this:

https://github.com/netbirdio/netbird/blob/86c4b7e6f47df1bf754dda735b97ce80c58422dc/infrastructure_files/configure.sh#L132-L152

Could you point me to which instructions you followed that were missing or provided incorrect information?

nazarewk avatar Jul 23 '25 10:07 nazarewk

Thank you for the fast response ;). I'm using nixos with the netbird module provided by nixpkgs, I'm using the nix option services.netbird.server.management.oidcConfigEndpoint. This value gets successfully written into /var/lib/netbird-mgmt/management.json but the web UI does not seem to use it.

arminfro avatar Jul 23 '25 10:07 arminfro

Same issue here. localhost/.well-known/openid-configuration:1 Failed to load resource: net::ERR_CONNECTION_REFUSED, on Netbird v0.52.0 with Authentik via Docker

In management container logs:

INFO [context: SYSTEM] management/cmd/management.go:528: loaded OIDC configuration from the provided IDP configuration endpoint: https://authentik.<domain_name>/application/o/netbird/.well-known/openid-configuration

successfully loaded, but I am not sure that localhost trying to access offline scope ?

HEKPYTO avatar Jul 30 '25 06:07 HEKPYTO

Facing the same issue: GET http://localhost/.well-known/openid-configuration 404 Not Found on Netbird 0.54.2 and dashboard v2.16.0 with Zitadel and k8s.

In management pod logs, I get:

2025-08-19T07:33:26Z INFO [context: SYSTEM] management/cmd/management.go:523: loading OIDC configuration from the provided IDP configuration endpoint https://<zitadel-domain>/.well-known/openid-configuration

Any fixes already?

dani3lsf avatar Aug 19 '25 07:08 dani3lsf

Hi, I am facing exactly the same issue using Keycloak. Are there any updates?

Thanks

jschlitt-kupona avatar Aug 19 '25 08:08 jschlitt-kupona

@dani3lsf @jschlitt-kupona can you try setting up NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT envvar? you should be able to provide an explicit address of the OIDC endpoint with it as per https://github.com/netbirdio/netbird/issues/2442#issuecomment-3106892099

nazarewk avatar Aug 19 '25 09:08 nazarewk

Thanks alot for your fast reply.

This is not working for me, still getting the same error.

Here is my configuration with keycloak and traefik:

docker-compose.yaml


x-default: &default
  restart: 'unless-stopped'
  logging:
    driver: 'json-file'
    options:
      max-size: '500m'
      max-file: '2'

services:
  # UI dashboard
  dashboard:
    <<: *default
    image: netbirdio/dashboard:latest
    container_name: netbird-dashboard
    environment:
      # Endpoints
      - NETBIRD_MGMT_API_ENDPOINT=https://netbird.my-domain.de:443
      - NETBIRD_MGMT_GRPC_API_ENDPOINT=https://netbird.my-domain.de:443
      # OIDC
      - AUTH_AUDIENCE=netbird-client
      - AUTH_CLIENT_ID=netbird-client
      - AUTH_CLIENT_SECRET=
      - AUTH_AUTHORITY=https://auth.my-domain.de/realms/my-realm
      - USE_AUTH0=false
      - AUTH_SUPPORTED_SCOPES=
      - AUTH_REDIRECT_URI=
      - AUTH_SILENT_REDIRECT_URI=
      - NETBIRD_TOKEN_SOURCE=accessToken
      - NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT=https://auth.my-domain.de/realms/my-realm/.well-known/openid-configuration
      # SSL
      - NGINX_SSL_PORT=443
      # Letsencrypt
      - LETSENCRYPT_DOMAIN=
      - LETSENCRYPT_EMAIL=
    # volumes:
    #   - netbird-letsencrypt:/etc/letsencrypt/
    networks:
      - proxy
      # - netbird
    labels:
    - traefik.enable=true
    - traefik.http.routers.netbird-dashboard.rule=Host(`netbird.my-domain.de`)
    - traefik.http.services.netbird-dashboard.loadbalancer.server.port=80
    - traefik.http.routers.netbird-dashboard.tls=true
    - traefik.http.routers.netbird-dashboard.tls.certresolver=letsencrypt-production

  # Signal
  signal:
    <<: *default
    image: netbirdio/signal:latest
    container_name: netbird-signal
    volumes:
      - ./data/netbird-signal:/var/lib/netbird
    networks:
      - proxy
      - netbird
    labels:
    - traefik.enable=true
    - traefik.http.routers.netbird-signal.rule=Host(`netbird.my-domain.de`) && PathPrefix(`/signalexchange.SignalExchange/`)
    - traefik.http.services.netbird-signal.loadbalancer.server.port=10000
    - traefik.http.services.netbird-signal.loadbalancer.server.scheme=h2c
    - traefik.http.routers.netbird-signal.tls=true
    - traefik.http.routers.netbird-signal.tls.certresolver=letsencrypt-production

  netbird-postgres:
    <<: *default
    image: postgres:latest
    container_name: netbird-postgres
    environment:
      POSTGRES_USER: netbird
      POSTGRES_PASSWORD: pg-password
      POSTGRES_DB: netbird
    volumes:
      - ./data/netbird-postgres:/var/lib/postgresql/data
    networks:
      - netbird

  # Relay
  relay:
    <<: *default
    image: netbirdio/relay:latest
    container_name: netbird-relay
    environment:
    - NB_LOG_LEVEL=info
    - NB_LISTEN_ADDRESS=:33080
    - NB_EXPOSED_ADDRESS=rels://netbird.my-domain.de:33080/relay
    # todo: change to a secure secret
    - NB_AUTH_SECRET=secret
    networks:
      - proxy
      - netbird
    labels:
    - traefik.enable=true
    - traefik.http.routers.netbird-relay.rule=Host(`netbird.my-domain.de`) && PathPrefix(`/relay`)
    - traefik.http.services.netbird-relay.loadbalancer.server.port=33080
    - traefik.http.services.netbird-relay.loadbalancer.server.scheme=h2c
    - traefik.http.routers.netbird-relay.tls=true
    - traefik.http.routers.netbird-relay.tls.certresolver=letsencrypt-production

  # Management
  management:
    <<: *default
    image: netbirdio/management:latest
    container_name: netbird-management
    depends_on:
      - dashboard
    volumes:
      - ./data/netbird-mgmt:/var/lib/netbird
      # - netbird-letsencrypt:/etc/letsencrypt:ro
      - ./management.json:/etc/netbird/management.json
    command: [
      "--port", "33073",
      "--log-file", "console",
      "--log-level", "info",
      "--disable-anonymous-metrics=false",
      "--single-account-mode-domain=netbird.my-domain.de",
      "--dns-domain=netbird.selfhosted"
      ]
    networks:
      - proxy
      - netbird
    labels:
    - traefik.enable=true
    - traefik.http.routers.netbird-api.rule=Host(`netbird.my-domain.de`) && PathPrefix(`/api`)
    - traefik.http.routers.netbird-api.service=netbird-api
    - traefik.http.services.netbird-api.loadbalancer.server.port=33073

    - traefik.http.routers.netbird-management.rule=Host(`netbird.my-domain.de`) && PathPrefix(`/management.ManagementService/`)
    - traefik.http.routers.netbird-management.service=netbird-management
    - traefik.http.services.netbird-management.loadbalancer.server.port=33073
    - traefik.http.services.netbird-management.loadbalancer.server.scheme=h2c
    - traefik.router.netbird-management.tls=true
    - traefik.router.netbird-management.tls.certresolver=letsencrypt-production
    environment:
      - NETBIRD_STORE_ENGINE_POSTGRES_DSN=postgres://netbird:pg-password@netbird-postgres:5432/netbird?sslmode=disable
      
  # Coturn
  coturn:
    <<: *default
    image: coturn/coturn:latest
    container_name: netbird-coturn
    domainname: netbird.my-domain.de
    volumes:
      - ./turnserver.conf:/etc/turnserver.conf:ro
    network_mode: host
    command:
      - -c /etc/turnserver.conf
    # neetworks:
    #   - netbird

# volumes:
  # netbird-mgmt:
  # netbird-signal:
  # netbird-letsencrypt:

networks:
  proxy:
    external: true
    name: proxy
  netbird:
    external: false
    name: netbird

management.json

{
    "Stuns": [
        {
            "Proto": "udp",
            "URI": "stun:netbird.my-domain.de:3478",
            "Username": "",
            "Password": ""
        }
    ],
    "TURNConfig": {
        "TimeBasedCredentials": false,
        "CredentialsTTL": "12h0m0s",
        "Secret": "secret",
        "Turns": [
            {
                "Proto": "udp",
                "URI": "turn:netbird.my-domain.de:3478",
                "Username": "self",
                "Password": "my-turn-password"
            }
        ]
    },
    "Relay": {
        "Addresses": [
            "rels://netbird.my-domain.de:33080/relay"
        ],
        "CredentialsTTL": "24h0m0s",
        "Secret": "my-relay-secret"
    },
    "Signal": {
        "Proto": "https",
        "URI": "netbird.my-domain.de:443",
        "Username": "",
        "Password": ""
    },
    "Datadir": "/var/lib/netbird/",
    "DataStoreEncryptionKey": "my-datastore-encryption-key",
    "HttpConfig": {
        "LetsEncryptDomain": "",
        "CertFile": "",
        "CertKey": "",
        "AuthAudience": "netbird-client",
        "AuthIssuer": "https://auth.my-domain.de/realms/my-realm",
        "AuthUserIDClaim": "",
        "AuthKeysLocation": "https://auth.my-domain.de/realms/my-realm/protocol/openid-connect/certs",
        "OIDCConfigEndpoint": "https://auth.my-domain.de/realms/my-realm/.well-known/openid-configuration",
        "IdpSignKeyRefreshEnabled": false,
        "ExtraAuthAudience": ""
    },
    "IdpManagerConfig": {
        "ManagerType": "keycloak",
        "ClientConfig": {
            "Issuer": "https://auth.my-domain.de/realms/my-realm",
            "TokenEndpoint": "https://auth.my-domain.de/realms/my-realm/protocol/openid-connect/token",
            "ClientID": "netbird-backend",
            "ClientSecret": "my-client-secret",
            "GrantType": "client_credentials"
        },
        "ExtraConfig": {
            "AdminEndpoint": "https://auth.my-domain.de/admin/realms/my-realm"
        },
        "Auth0ClientCredentials": null,
        "AzureClientCredentials": null,
        "KeycloakClientCredentials": null,
        "ZitadelClientCredentials": null
    },
    "DeviceAuthorizationFlow": {
        "Provider": "none",
        "ProviderConfig": {
            "ClientID": "",
            "ClientSecret": "",
            "Domain": "",
            "Audience": "netbird-client",
            "TokenEndpoint": "https://auth.my-domain.de/realms/my-realm/protocol/openid-connect/token",
            "DeviceAuthEndpoint": "https://auth.my-domain.de/realms/my-realm/protocol/openid-connect/auth/device",
            "AuthorizationEndpoint": "",
            "Scope": "openid",
            "UseIDToken": false,
            "RedirectURLs": null,
            "DisablePromptLogin": false,
            "LoginFlag": 0
        }
    },
    "PKCEAuthorizationFlow": {
        "ProviderConfig": {
            "ClientID": "netbird-client",
            "ClientSecret": "",
            "Domain": "",
            "Audience": "netbird-client",
            "TokenEndpoint": "https://auth.my-domain.de/realms/my-realm/protocol/openid-connect/token",
            "DeviceAuthEndpoint": "",
            "AuthorizationEndpoint": "https://auth.my-domain.de/realms/my-realm/protocol/openid-connect/auth",
            "Scope": "",
            "UseIDToken": false,
            "DisablePromptLogin": false,
            "LoginFlag": 0
        }
    },
    "StoreConfig": {
        "Engine": "postgres"
    },
    "ReverseProxy": {
        "TrustedHTTPProxies": [],
        "TrustedHTTPProxiesCount": 0,
        "TrustedPeers": [
            "0.0.0.0/0"
        ]
    },
    "DisableDefaultPolicy": false
}

This is the error in the browser console:

Image

Here are the dashboards container logs:

+ LETSENCRYPT_DOMAIN=none

+ LETSENCRYPT_EMAIL=example@local

+ NGINX_SSL_PORT=443

+ '[' none-x == none-x ']'

+ exit 0

AUTH_SUPPORTED_SCOPES environment variable must be set

+ LETSENCRYPT_DOMAIN=none

+ LETSENCRYPT_EMAIL=example@local

+ NGINX_SSL_PORT=443

+ '[' none-x == none-x ']'

+ exit 0

I hope somebody can help me out.

Best regards

Jonathan

jschlitt-kupona avatar Aug 19 '25 09:08 jschlitt-kupona

@jschlitt-kupona I was able to make it work. For me was missing the:

  • NGINX_SSL_PORT=443 Also removed the :443 suffix from NETBIRD_MGMT_API_ENDPOINT and NETBIRD_MGMT_GRPC_API_ENDPOINT env variables

dani3lsf avatar Aug 19 '25 10:08 dani3lsf

@dani3lsf I had no luck setting it up. There are no other errors, and only the Dashboard is trying to connect to localhost and not to the Keycloak domain and realm.

http://localhost/.well-known/openid-configuration

should be

https://auth.my-domain/realms/my-realm/.well-known/openid-configuration

I was not able to find the frontend source code of the Next.js dashboard to find the implementation, where the localhost value was set and which env variables are involved.

I hope somebody has a deeper understanding of the implementation and can tell me where the env variable is set so we can find a possible solution together.

jschlitt-kupona avatar Aug 19 '25 12:08 jschlitt-kupona

@jschlitt-kupona could ou post your setup.env file content (redacting out the sensitive information)? Feel free to send it to [email protected] if you don't want to share publicly.

nazarewk avatar Aug 19 '25 15:08 nazarewk

Hello @nazarewk.

Thanks a lot for your answer.

These are my setup.env file's contents. What am I missing, or what is misconfigured here?

I hope you can support me by fixing my installation...

Otherwise I will go with the hosted option until the problem is solved.

## example file, you can copy this file to setup.env and update its values
##

# Image tags
# you can force specific tags for each component; will be set to latest if empty
NETBIRD_DASHBOARD_TAG=""
NETBIRD_SIGNAL_TAG=""
NETBIRD_MANAGEMENT_TAG=""
COTURN_TAG=""
NETBIRD_RELAY_TAG=""

# Dashboard domain. e.g. app.mydomain.com
NETBIRD_DOMAIN="netbird.<my-domain>"

# TURN server domain. e.g. turn.mydomain.com
# if not specified it will assume NETBIRD_DOMAIN
NETBIRD_TURN_DOMAIN=""

# TURN server public IP address
# required for a connection involving peers in
# the same network as the server and external peers
# usually matches the IP for the domain set in NETBIRD_TURN_DOMAIN
NETBIRD_TURN_EXTERNAL_IP="<my-external-ip>"

# -------------------------------------------
# OIDC
#  e.g., https://example.eu.auth0.com/.well-known/openid-configuration
# -------------------------------------------
NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT="https://<my-keycloak-domain>/realms/<my-realm>/.well-known/openid-configuration"
NETBIRD_USE_AUTH0=false
NETBIRD_AUTH_CLIENT_ID="netbird-client"
NETBIRD_AUTH_SUPPORTED_SCOPES="openid profile email offline_access api"
NETBIRD_AUTH_AUDIENCE="netbird-client"

NETBIRD_AUTH_DEVICE_AUTH_CLIENT_ID="netbird-client"
NETBIRD_AUTH_DEVICE_AUTH_AUDIENCE="netbird-client"

NETBIRD_MGMT_IDP="keycloak"
NETBIRD_IDP_MGMT_CLIENT_ID="netbird-backend"
NETBIRD_IDP_MGMT_CLIENT_SECRET="<my-client-secret>"
NETBIRD_IDP_MGMT_EXTRA_ADMIN_ENDPOINT="https://<my-keycloak-domain>/admin/realms/<my-realm>"


# The default setting is to transmit the audience to the IDP during authorization. However,
# if your IDP does not have this capability, you can turn this off by setting it to false.
#NETBIRD_DASH_AUTH_USE_AUDIENCE=false
NETBIRD_AUTH_AUDIENCE="netbird-client"
# e.g. netbird-client
NETBIRD_AUTH_CLIENT_ID="netbird-client"
# indicates the scopes that will be requested to the IDP
NETBIRD_AUTH_SUPPORTED_SCOPES=""
# NETBIRD_AUTH_CLIENT_SECRET is required only by Google workspace.
# NETBIRD_AUTH_CLIENT_SECRET=""
# if you want to use a custom claim for the user ID instead of 'sub', set it here
# NETBIRD_AUTH_USER_ID_CLAIM=""
# indicates whether to use Auth0 or not: true or false
NETBIRD_USE_AUTH0="false"
# if your IDP provider doesn't support fragmented URIs, configure custom
# redirect and silent redirect URIs, these will be concatenated into your NETBIRD_DOMAIN domain.
# NETBIRD_AUTH_REDIRECT_URI="/peers"
# NETBIRD_AUTH_SILENT_REDIRECT_URI="/add-peers"
# Updates the preference to use id tokens instead of access token on dashboard
# Okta and Gitlab IDPs can benefit from this
# NETBIRD_TOKEN_SOURCE="idToken"
# -------------------------------------------
# OIDC Device Authorization Flow
# -------------------------------------------
NETBIRD_AUTH_DEVICE_AUTH_PROVIDER="none"
NETBIRD_AUTH_DEVICE_AUTH_CLIENT_ID=""
# Some IDPs requires different audience, scopes and to use id token for device authorization flow
# you can customize here:
NETBIRD_AUTH_DEVICE_AUTH_AUDIENCE=$NETBIRD_AUTH_AUDIENCE
NETBIRD_AUTH_DEVICE_AUTH_SCOPE="openid"
NETBIRD_AUTH_DEVICE_AUTH_USE_ID_TOKEN=false
# -------------------------------------------
# OIDC PKCE Authorization Flow
# -------------------------------------------
# Comma separated port numbers. if already in use, PKCE flow will choose an available port from the list as an alternative
# eg. 53000,54000
NETBIRD_AUTH_PKCE_REDIRECT_URL_PORTS="53000"
# -------------------------------------------
# IDP Management
# -------------------------------------------
# eg. zitadel, auth0, azure, keycloak
# NETBIRD_MGMT_IDP="keycloak"
# Some IDPs requires different client id and client secret for management api
# NETBIRD_IDP_MGMT_CLIENT_ID=$NETBIRD_AUTH_CLIENT_ID
# NETBIRD_IDP_MGMT_CLIENT_SECRET="NGFFxJbnU7PS4Z4t6B5SgZYuI2PtMafC"
# Required when setting up with Keycloak "https://<YOUR_KEYCLOAK_HOST_AND_PORT>/admin/realms/netbird"
# NETBIRD_IDP_MGMT_EXTRA_ADMIN_ENDPOINT=
# With some IDPs may be needed enabling automatic refresh of signing keys on expire
# NETBIRD_MGMT_IDP_SIGNKEY_REFRESH=false
# NETBIRD_IDP_MGMT_EXTRA_ variables. See https://docs.netbird.io/selfhosted/identity-providers for more information about your IDP of choice.
# -------------------------------------------
# Letsencrypt
# -------------------------------------------
# Disable letsencrypt
#  if disabled, cannot use HTTPS anymore and requires setting up a reverse-proxy to do it instead
NETBIRD_DISABLE_LETSENCRYPT=true
# e.g. [email protected]
NETBIRD_LETSENCRYPT_EMAIL=""
# -------------------------------------------
# Extra settings
# -------------------------------------------
# Disable anonymous metrics collection, see more information at https://netbird.io/docs/FAQ/metrics-collection
NETBIRD_DISABLE_ANONYMOUS_METRICS=false
# DNS DOMAIN configures the domain name used for peer resolution. By default it is netbird.selfhosted
NETBIRD_MGMT_DNS_DOMAIN=netbird.selfhosted
# Disable default all-to-all policy for new accounts
NETBIRD_MGMT_DISABLE_DEFAULT_POLICY=false
# -------------------------------------------
# Relay settings
# -------------------------------------------
# Relay server domain. e.g. relay.mydomain.com
# if not specified it will assume NETBIRD_DOMAIN
NETBIRD_RELAY_DOMAIN=""

# Relay server connection port. If none is supplied
# it will default to 33080
# should be updated to match TLS-port of reverse proxy when netbird is running behind reverse proxy
NETBIRD_RELAY_PORT=""

# Management API connecting port. If none is supplied
# it will default to 33073
# should be updated to match TLS-port of reverse proxy when netbird is running behind reverse proxy
NETBIRD_MGMT_API_PORT="443"

# Signal service connecting port. If none is supplied
# it will default to 10000
# should be updated to match TLS-port of reverse proxy when netbird is running behind reverse proxy
NETBIRD_SIGNAL_PORT="443"

NETBIRD_STORE_CONFIG_ENGINE=postgres
NETBIRD_STORE_ENGINE_POSTGRES_DSN="postgres://netbird:netbird@netbird-postgres:5432/netbird?sslmode=disable"

# -------------------------------------------
# I followed the instructions to set up netbird with the traefik reverse proxy, so I used the docker-compose.yml.tmpl.traefik template file.
# -------------------------------------------

jschlitt-kupona avatar Aug 20 '25 18:08 jschlitt-kupona

@jschlitt-kupona @jonathanschlitt the setup.env looks fine, can you confirm that curl "$NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT" returns the expected JSON data?

Is the previously mentioned docker-compose.yml the one you are currently using? Could you post your current version if it isn't?

nazarewk avatar Aug 22 '25 16:08 nazarewk

It is the current compose file.

jonathanschlitt avatar Aug 22 '25 16:08 jonathanschlitt

The URL of the "$NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT" returns the following data but is not used in the Netbird-Dashboard.

https://<my-keycloak-domain>/realms/<my-realm>/.well-known/openid-configuration

{
  "issuer": "https://<my-keycloak-domain>/realms/<my-realm>",
  "authorization_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/auth",
  "token_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/token",
  "introspection_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/token/introspect",
  "userinfo_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/userinfo",
  "end_session_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/logout",
  "frontchannel_logout_session_supported": true,
  "frontchannel_logout_supported": true,
  "jwks_uri": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/certs",
  "check_session_iframe": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/login-status-iframe.html",
  "grant_types_supported": [
    "authorization_code",
    "implicit",
    "refresh_token",
    "password",
    "client_credentials",
    "urn:openid:params:grant-type:ciba",
    "urn:ietf:params:oauth:grant-type:device_code"
  ],
  "acr_values_supported": ["0", "1"],
  "response_types_supported": [
    "code",
    "none",
    "id_token",
    "token",
    "id_token token",
    "code id_token",
    "code token",
    "code id_token token"
  ],
  "subject_types_supported": ["public", "pairwise"],
  "id_token_signing_alg_values_supported": [
    "PS384",
    "RS384",
    "EdDSA",
    "ES384",
    "HS256",
    "HS512",
    "ES256",
    "RS256",
    "HS384",
    "ES512",
    "PS256",
    "PS512",
    "RS512"
  ],
  "id_token_encryption_alg_values_supported": ["RSA-OAEP", "RSA-OAEP-256", "RSA1_5"],
  "id_token_encryption_enc_values_supported": [
    "A256GCM",
    "A192GCM",
    "A128GCM",
    "A128CBC-HS256",
    "A192CBC-HS384",
    "A256CBC-HS512"
  ],
  "userinfo_signing_alg_values_supported": [
    "PS384",
    "RS384",
    "EdDSA",
    "ES384",
    "HS256",
    "HS512",
    "ES256",
    "RS256",
    "HS384",
    "ES512",
    "PS256",
    "PS512",
    "RS512",
    "none"
  ],
  "userinfo_encryption_alg_values_supported": ["RSA-OAEP", "RSA-OAEP-256", "RSA1_5"],
  "userinfo_encryption_enc_values_supported": [
    "A256GCM",
    "A192GCM",
    "A128GCM",
    "A128CBC-HS256",
    "A192CBC-HS384",
    "A256CBC-HS512"
  ],
  "request_object_signing_alg_values_supported": [
    "PS384",
    "RS384",
    "EdDSA",
    "ES384",
    "HS256",
    "HS512",
    "ES256",
    "RS256",
    "HS384",
    "ES512",
    "PS256",
    "PS512",
    "RS512",
    "none"
  ],
  "request_object_encryption_alg_values_supported": ["RSA-OAEP", "RSA-OAEP-256", "RSA1_5"],
  "request_object_encryption_enc_values_supported": [
    "A256GCM",
    "A192GCM",
    "A128GCM",
    "A128CBC-HS256",
    "A192CBC-HS384",
    "A256CBC-HS512"
  ],
  "response_modes_supported": ["query", "fragment", "form_post", "query.jwt", "fragment.jwt", "form_post.jwt", "jwt"],
  "registration_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/clients-registrations/openid-connect",
  "token_endpoint_auth_methods_supported": [
    "private_key_jwt",
    "client_secret_basic",
    "client_secret_post",
    "tls_client_auth",
    "client_secret_jwt"
  ],
  "token_endpoint_auth_signing_alg_values_supported": [
    "PS384",
    "RS384",
    "EdDSA",
    "ES384",
    "HS256",
    "HS512",
    "ES256",
    "RS256",
    "HS384",
    "ES512",
    "PS256",
    "PS512",
    "RS512"
  ],
  "introspection_endpoint_auth_methods_supported": [
    "private_key_jwt",
    "client_secret_basic",
    "client_secret_post",
    "tls_client_auth",
    "client_secret_jwt"
  ],
  "introspection_endpoint_auth_signing_alg_values_supported": [
    "PS384",
    "RS384",
    "EdDSA",
    "ES384",
    "HS256",
    "HS512",
    "ES256",
    "RS256",
    "HS384",
    "ES512",
    "PS256",
    "PS512",
    "RS512"
  ],
  "authorization_signing_alg_values_supported": [
    "PS384",
    "RS384",
    "EdDSA",
    "ES384",
    "HS256",
    "HS512",
    "ES256",
    "RS256",
    "HS384",
    "ES512",
    "PS256",
    "PS512",
    "RS512"
  ],
  "authorization_encryption_alg_values_supported": ["RSA-OAEP", "RSA-OAEP-256", "RSA1_5"],
  "authorization_encryption_enc_values_supported": [
    "A256GCM",
    "A192GCM",
    "A128GCM",
    "A128CBC-HS256",
    "A192CBC-HS384",
    "A256CBC-HS512"
  ],
  "claims_supported": [
    "aud",
    "sub",
    "iss",
    "auth_time",
    "name",
    "given_name",
    "family_name",
    "preferred_username",
    "email",
    "acr"
  ],
  "claim_types_supported": ["normal"],
  "claims_parameter_supported": true,
  "scopes_supported": [
    "openid",
    "address",
    "microprofile-jwt",
    "api",
    "profile",
    "email",
    "roles",
    "web-origins",
    "acr",
    "phone",
    "offline_access"
  ],
  "request_parameter_supported": true,
  "request_uri_parameter_supported": true,
  "require_request_uri_registration": true,
  "code_challenge_methods_supported": ["plain", "S256"],
  "tls_client_certificate_bound_access_tokens": true,
  "revocation_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/revoke",
  "revocation_endpoint_auth_methods_supported": [
    "private_key_jwt",
    "client_secret_basic",
    "client_secret_post",
    "tls_client_auth",
    "client_secret_jwt"
  ],
  "revocation_endpoint_auth_signing_alg_values_supported": [
    "PS384",
    "RS384",
    "EdDSA",
    "ES384",
    "HS256",
    "HS512",
    "ES256",
    "RS256",
    "HS384",
    "ES512",
    "PS256",
    "PS512",
    "RS512"
  ],
  "backchannel_logout_supported": true,
  "backchannel_logout_session_supported": true,
  "device_authorization_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/auth/device",
  "backchannel_token_delivery_modes_supported": ["poll", "ping"],
  "backchannel_authentication_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/ext/ciba/auth",
  "backchannel_authentication_request_signing_alg_values_supported": [
    "PS384",
    "RS384",
    "EdDSA",
    "ES384",
    "ES256",
    "RS256",
    "ES512",
    "PS256",
    "PS512",
    "RS512"
  ],
  "require_pushed_authorization_requests": false,
  "pushed_authorization_request_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/ext/par/request",
  "mtls_endpoint_aliases": {
    "token_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/token",
    "revocation_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/revoke",
    "introspection_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/token/introspect",
    "device_authorization_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/auth/device",
    "registration_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/clients-registrations/openid-connect",
    "userinfo_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/userinfo",
    "pushed_authorization_request_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/ext/par/request",
    "backchannel_authentication_endpoint": "https://<my-keycloak-domain>/realms/<my-realm>/protocol/openid-connect/ext/ciba/auth"
  },
  "authorization_response_iss_parameter_supported": true
}

jschlitt-kupona avatar Aug 24 '25 15:08 jschlitt-kupona

@jonathanschlitt looks like you're not setting the AUTH_SUPPORTED_SCOPES environment variable to a meaningful value. Please see other relevant envvars for the Dashboard.

Seems like you might not have carried over the other setup.env variables, did you run configure.sh after you changed those?

the relevant log

Here are the dashboards container logs:

+ LETSENCRYPT_DOMAIN=none

+ LETSENCRYPT_EMAIL=example@local

+ NGINX_SSL_PORT=443

+ '[' none-x == none-x ']'

+ exit 0

AUTH_SUPPORTED_SCOPES environment variable must be set

+ LETSENCRYPT_DOMAIN=none

+ LETSENCRYPT_EMAIL=example@local

+ NGINX_SSL_PORT=443

+ '[' none-x == none-x ']'

+ exit 0

I hope somebody can help me out.

nazarewk avatar Aug 27 '25 12:08 nazarewk