Open oddlama opened 4 months ago
Hello @oddlama,
- I'm not sure why the email address is not populated, since the requested oauth scopes are openid profile email, so the information must be available
NetBird does not store detailed user information except for the UserID. To populate user data such as the username and email address, NetBird retrieves this information from the Identity Provider (IdP) via REST API calls, as OIDC does not support fetching a list of user accounts directly.
Currently, NetBird supports fetching user data from IdPs like Auth0, Azure, Okta, Google Workspace, JumpCloud, Zitadel, Authentik, and Keycloak. Unfortunately, your IdP, Kanidm, is not yet supported. However, you can bridge your account with any of the supported IdPs mentioned above to ensure that user information, including email addresses, is correctly populated.
- When trying to login from a mobile device, it starts the oauth flow and after successfully logging in the app stays in Connecting... for around 30 seconds and finally fails with an error. The server log then shows unable to fetch account with claims, err: user ID is empty:
NetBird relies on the AuthUserIDClaim
internally to extract the userID from the access token to identify the user account. This means that the AuthUserIDClaim must be set to the correct claim that contains the unique identifier of the user in your IdP. By default the AuthUserIDClaim
will be set to sub
.
In your case, it appears that the AuthUserIDClaim is either empty or incorrectly set, which is why the server log shows "unable to fetch account with claims, err: user ID is empty." Please ensure that the AuthUserIDClaim is configured to the correct claim containing the userID in your IdP settings.
Currently, NetBird supports fetching user data from IdPs like Auth0, Azure, Okta, Google Workspace, JumpCloud, Zitadel, Authentik, and Keycloak. Unfortunately, your IdP, Kanidm, is not yet supported. However, you can bridge your account with any of the supported IdPs mentioned above to ensure that user information, including email addresses, is correctly populated.
Interesting, so netbird basically wants to pre-populate the list of all users? Sounds like a lot of work to maintain a specific implementation for each IDP. Is there a chance to get a agnostic OIDC-compatible mode, which populates user data on first login instead? That would have the downside of not being able to see all users immediately but at least their information would be available regardelss of which IDP is in use, without requiring netbird to write any more integrations.
NetBird relies on the
AuthUserIDClaim
internally to extract the userID from the access token to identify the user account. This means that the AuthUserIDClaim must be set to the correct claim that contains the unique identifier of the user in your IdP. By default theAuthUserIDClaim
will be set tosub
.
I see, this is kind of what I assumed. But then I don't really understand why this setting exists, because the OIDC spec quoted above basically requires netbird to use the sub
claim as an identifier. Anything else is not stable and could change. So from my limited understanding, changing this setting sounds like making netbird violate the OIDC spec. Am I missing something essential here? When is that option used in a real world scenario?
In your case, it appears that the AuthUserIDClaim is either empty or incorrectly set, which is why the server log shows "unable to fetch account with claims, err: user ID is empty." Please ensure that the AuthUserIDClaim is configured to the correct claim containing the userID in your IdP settings.
So this means that the preferred_username
is not present the oauth response by the flow initiated by the mobile device. But the IDP doesn't care whether a mobile device or web browser makes the request, so that leads me to believe that there is something different about the flow initiated on the mobile device, because it only fails there. Do you have any leads on what could be different?
A final question: How does netbird link user accounts? Is there a separate concept of usernames and user ids, or is the username the same as the user id? I'd like netbird to use sub
as the id for identifying accounts but still get a humanly readable name for it from the preferred_username
claim on first login.
Interesting, so netbird basically wants to pre-populate the list of all users? Sounds like a lot of work to maintain a specific implementation for each IDP. Is there a chance to get a agnostic OIDC-compatible mode, which populates user data on first login instead? That would have the downside of not being able to see all users immediately but at least their information would be available regardelss of which IDP is in use, without requiring netbird to write any more integrations.
Yes, for self-hosted, it will populate the list of all users allowed to have access in IdP. At the moment, you can open a feature request for support of OIDC-compatible mode.
I see, this is kind of what I assumed. But then I don't really understand why this setting exists, because the OIDC spec quoted above basically requires netbird to use the sub claim as an identifier. Anything else is not stable and could change. So from my limited understanding, changing this setting sounds like making netbird violate the OIDC spec. Am I missing something essential here? When is that option used in a real world scenario?
This is because different IdPs have varying behaviors and support for access tokens and ID tokens. For instance, to ensure Netbird works correctly with Azure AD (Microsoft Entra ID), the AuthUserIDClaim
must be set to oid
, which maps the correct user ID from the ID token
So this means that the preferred_username is not present the oauth response by the flow initiated by the mobile device. But the IDP doesn't care whether a mobile device or web browser makes the request, so that leads me to believe that there is something different about the flow initiated on the mobile device, because it only fails there. Do you have any leads on what could be different?
There is a possibility that this is not set, as NetBird extracts these claims from the token generated by your IdP. Unfortunately, at the moment, I don't have any specific leads on what might be causing this difference
A final question: How does netbird link user accounts? Is there a separate concept of usernames and user ids, or is the username the same as the user id? I'd like netbird to use sub as the id for identifying accounts but still get a humanly readable name for it from the preferred_username claim on first login.
Netbird relies on the user ID to link accounts from your IdP. The username and user ID could be the same or different, again, this depends on the specific IdP implementation. However, in the majority of cases, the username represents the user's full name, while the user ID serves as the unique identifier for the user within your IdP
Netbird is searching for AuthUserIDClaim
(e.g., name
, email
) in access tokens, but these fields only present in ID tokens, Netbird should extract them from ID tokens.
Netbird is searching for
AuthUserIDClaim
(e.g.,name
,
NetBird currently extracts only the userID from the token. Other user attributes, such as name and email, are not extracted from the token. Instead, these attributes are retrieved directly from the Identity Provider (IdP).
@oddlama You can switch to the ID Token by configuring NETBIRD_AUTH_DEVICE_AUTH_USE_ID_TOKEN=true
and NETBIRD_TOKEN_SOURCE=idToken
in your setup.env
file. However, it's essential to note that this change will require recreating the DB
@bcmmbaga Thanks, thats great to know! I'll test that later
Describe the problem
I want to use
preferred_username
as the AuthUserIDClaim so that I can identify the accounts in my instance. Currently I'm using kanidm as my IDP and thesub
value leads to randomly generated UUIDs, which makes it impossible to easily distinguish accounts:Correct me if I am wrong, but it looks to me like the
AuthUserIDClaim
determines the name for accounts. I would have expected it to be namedAuthUsernameClaim
or something like that since thesub
claim from the OIDC spec should always be used for the ID.Now there are two issues:
openid profile email
, so the information must be availableWhen trying to login from a mobile device, it starts the oauth flow and after successfully logging in the app stays in
Connecting...
for around 30 seconds and finally fails with an error. The server log then showsunable to fetch account with claims, err: user ID is empty
:This message repeats several times. As soon as I remove
AuthUserIDClaim
from my config (or set it tosub
) it will start working as expected without errors.Logging in on the webinterface still works fine, showing the correct user name:
But I noticed that this will count as a new account, which is weird because the
sub
claim didn't change. Section 5.7 of the core OIDC spec states: "The sub (subject) and iss (issuer) Claims, used together, are the only Claims that an RP can rely upon as a stable identifier for the End-User, [...] other Claims such as email, phone_number, and preferred_username MUST NOT be used as unique identifiers for the End-User."I might be misunderstanding what netbird does internally, but it seems to me as if it uses
AuthUserIDClaim
as both the identifier and username. This would essentially force users to always set this attribute tosub
because all other claims would not be stable.To Reproduce
Steps to reproduce the behavior:
AuthUserIDClaim
to preferred_usernameunable to fetch account with claims, err: user ID is empty
Expected behavior
sub
claim), but the username should reflect the settingemail
oidc scopeAre you using NetBird Cloud?
No, using self-hosted.
NetBird version
0.27.7
Additional context
My `management.json` file
```json { "DataStoreEncryptionKey": "---REDACTED---", "Datadir": "/var/lib/netbird-mgmt/data", "DeviceAuthorizationFlow": { "Provider": "none", "ProviderConfig": { "Audience": "netbird", "ClientID": "netbird", "DeviceAuthEndpoint": "", "Domain": null, "Scope": "openid profile email", "TokenEndpoint": null, "UseIDToken": false } }, "HttpConfig": { "Address": "127.0.0.1:8011", "AuthAudience": "netbird", "AuthUserIDClaim": "preferred_username", "IdpSignKeyRefreshEnabled": true, "OIDCConfigEndpoint": "https://mykanidminstance.example.com/oauth2/openid/netbird/.well-known/openid-configuration" }, "IdpManagerConfig": { "Auth0ClientCredentials": null, "AzureClientCredentials": null, "ClientConfig": { "ClientID": "netbird", "ClientSecret": "", "GrantType": "client_credentials", "Issuer": "", "TokenEndpoint": "" }, "ExtraConfig": {}, "KeycloakClientCredentials": null, "ManagerType": "none", "ZitadelClientCredentials": null }, "PKCEAuthorizationFlow": { "ProviderConfig": { "Audience": "netbird", "AuthorizationEndpoint": "", "ClientID": "netbird", "ClientSecret": "", "RedirectURLs": [ "http://localhost:53000" ], "Scope": "openid profile email", "TokenEndpoint": "", "UseIDToken": false } }, "ReverseProxy": { "TrustedHTTPProxies": [], "TrustedHTTPProxiesCount": 0, "TrustedPeers": [ "0.0.0.0/0" ] }, "Signal": { "Password": null, "Proto": "https", "URI": "mynetbirdinstance.example.com:443", "Username": "" }, "StoreConfig": { "Engine": "sqlite" }, "Stuns": [ { "Password": null, "Proto": "udp", "URI": "stun:mycoturn.example.com:3478", "Username": "" } ], "TURNConfig": { "CredentialsTTL": "12h", "Secret": "--REDACTED--", "TimeBasedCredentials": false, "Turns": [ { "Password": "--REDACTED--", "Proto": "udp", "URI": "turn:mycoturn.example.com:5349", "Username": "netbird" } ] } } ```