diff --git a/Enabling-SSO-support-using-OpenId-Connect.md b/Enabling-SSO-support-using-OpenId-Connect.md index 1dbb13e..65f50e5 100644 --- a/Enabling-SSO-support-using-OpenId-Connect.md +++ b/Enabling-SSO-support-using-OpenId-Connect.md @@ -16,7 +16,7 @@ The following configurations are available - `SSO_ALLOW_UNKNOWN_EMAIL_VERIFICATION`: Allow unknown email verification status (default `false`). Allowing this with `SSO_SIGNUPS_MATCH_EMAIL` open potential account takeover. - `SSO_AUTHORITY` : the OpenID Connect Discovery endpoint of your SSO - Should not include the `/.well-known/openid-configuration` part and no trailing `/` - - $SSO_AUTHORITY/.well-known/openid-configuration should return the a json document: https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse + - `${SSO_AUTHORITY}/.well-known/openid-configuration` must return a JSON document: https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse (with an [HTTP status code 200 OK](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse:~:text=A%20successful%20response%20MUST%20use%20the%20200%20OK%20HTTP%20status%20code)!) - `SSO_SCOPES` : Optional, allow to override scopes if needed (default `"email profile"`) - `SSO_AUTHORIZE_EXTRA_PARAMS` : Optional, allow to add extra parameter to the authorize redirection (default `""`) - `SSO_PKCE`: Activate PKCE for the Auth Code flow (default `true`). @@ -28,7 +28,7 @@ The following configurations are available - `SSO_CLIENT_CACHE_EXPIRATION`: Cache calls to the discovery endpoint, duration in seconds, `0` to disable (default `0`); - `SSO_DEBUG_TOKENS`: Log all tokens for easier debugging (default `false`, `LOG_LEVEL=debug` or `LOG_LEVEL=info,vaultwarden::sso=debug` need to be set) -The callback url is : `https://your.domain/identity/connect/oidc-signin` +The callback URL is [automatically generated](https://github.com/dani-garcia/vaultwarden/blob/1e1f9957cd037fad87e5cd33245720f865942016/src/config.rs#L1333) from the `DOMAIN`. If you set `DOMAIN=https://vaultwarden.example.tld` your callback URL will be `https://vaultwarden.example.tld/identity/connect/oidc-signin`. ## Account and Email handling @@ -37,8 +37,8 @@ This is used to link to the SSO provider identifier without changing the default - Storing the SSO identifier is important to prevent account takeover due to email change. - We can't use the identifier as the User uuid since it's way longer (Max 255 chars for the `sub` part, cf [spec](https://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken)). -- We want to be able to associate existing account based on `email` but only when the user logs in for the first time (controlled by `SSO_SIGNUPS_MATCH_EMAIL`). -- We need to be able to associate with existing stub account, such as the one created when inviting a user to an org (association is possible only if the user does not have a private key). +- We want to be able to associate existing accounts based on their `email` but only when a user logs in for the first time (controlled by `SSO_SIGNUPS_MATCH_EMAIL`). +- We need to be able to associate with existing stub accounts, such as the one created when inviting a user to an org (association is possible only if a user does not have a private key). Additionally: @@ -47,7 +47,7 @@ Additionally: On login if the email returned by the provider is not the one saved an email will be sent to the user to ask him to update it. - If set, `SIGNUPS_DOMAINS_WHITELIST` is applied on SSO signup and when attempting to change the email. -This means that if you ever need to change the provider url or the provider itself; you'll have to first delete the association +This means that if you ever need to change the provider URL or the provider itself; you'll have to first delete the association then ensure that `SSO_SIGNUPS_MATCH_EMAIL` is activated to allow a new association. To delete the association (this has no impact on the `Vaultwarden` user): @@ -58,13 +58,13 @@ TRUNCATE TABLE sso_users; ### On `SSO_ALLOW_UNKNOWN_EMAIL_VERIFICATION` -If your provider does not send the verification status of emails (`email_verified` [claim](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims)) you will need to activate this setting. +If your provider does not send the verification status of emails (`email_verified` [claim](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims)) you need to activate this setting. If set with `SSO_SIGNUPS_MATCH_EMAIL=true` (the default), then a user can associate with an existing, non-SSO account, even if they do not control the email address. This allow a user to gain access to sensitive information but the master password is still required to read the passwords. As such when using `SSO_ALLOW_UNKNOWN_EMAIL_VERIFICATION` it is recommended to disable `SSO_SIGNUPS_MATCH_EMAIL`. -If you need to associate non sso users try to keep both settings activated for the shortest time possible. +If you need to associate non SSO users try to keep both settings activated for the shortest time possible. ## Client Cache @@ -78,7 +78,7 @@ As a protection against a misconfigured expiration if the validation of the `IdT ### Google example (Rolling keys) If we take Google as an example checking the discovery [endpoint](https://accounts.google.com/.well-known/openid-configuration) response headers we can see that the `max-age` of the cache control is set to `3600` seconds. And the [jwk_uri](https://www.googleapis.com/oauth2/v3/certs) response headers usually contain a `max-age` with an even bigger value. -/ +\ Combined with user [feedback](https://github.com/ramosbugs/openidconnect-rs/issues/152) we can conclude that Google will roll the signing keys each week. Setting the cache expiration too high has diminishing return but using something like `600` (10 min) should provide plenty benefits. @@ -103,14 +103,14 @@ Or for a specific client in `Clients / Client details / Advanced / Advanced sett Server configuration, nothing specific just set: -- `SSO_AUTHORITY=https://${domain}/realms/${realm_name}` +- `SSO_AUTHORITY=https://${keycloak_domain}/realms/${realm_name}` - `SSO_CLIENT_ID` - `SSO_CLIENT_SECRET` ### Testing If you want to run a testing instance of Keycloak the Playwright [docker-compose](https://github.com/dani-garcia/vaultwarden/blob/main/playwright/docker-compose.yml) can be used. -\ + More details on how to use it in [README.md](https://github.com/dani-garcia/vaultwarden/blob/main/playwright/README.md#openid-connect-test-setup). ## Auth0 @@ -138,40 +138,41 @@ Starting with `2024.2` version you will need to add the `offline_access` scope a Server configuration should look like: -- `SSO_AUTHORITY=https://${domain}/application/o/${application_name}/` : trailing `/` is important +- `SSO_AUTHORITY=https://${authentik_domain}/application/o/${application_name}/` : trailing `/` is important - `SSO_SCOPES="email profile offline_access"` - `SSO_CLIENT_ID` - `SSO_CLIENT_SECRET` ### Troubleshooting -- `Failed to discover OpenID provider: Failed to parse server response`: - - First ensure that the Authority endpoint with `/.well-known/openid-configuration` appended is reacheable. - - Next check that the document return `id_token_signing_alg_values_supported: ["RS256"]`\ - If it returns `HS256` then selecting the default signing key again should fix the issue.\ - Steps: - 1. Open **Authentik admin panel** > **Providers** > Open your **Vaultwarden provider** - 2. Click **Edit** > Change the **Signing key** to any of your keys - - If unsure choose the built-in one from Authentik - 3. Click **Update** - 4. Retry +#### `Failed to discover OpenID provider: Failed to parse server response`: +First ensure that the Authority endpoint with `/.well-known/openid-configuration` appended is reachable from your Vaultwarden container. + +Next check that the response contains `id_token_signing_alg_values_supported: ["RS256"] + +If it returns `HS256` instead then selecting the default signing key again should fix the issue.\ +Steps: + 1. Open **Authentik admin panel** > **Providers** > Open your **Vaultwarden provider** + 2. Click **Edit** > Change the **Signing key** to any of your keys + - If unsure choose the built-in one from Authentik + 3. Click **Update** + 4. Retry -- `Failed to contact token endpoint: Parse(Error ... Invalid JSON web token: found 5 parts`: \ - This error is probably due to an encrypted token (JWE), ensure that no encryption key is used.\ - Steps: - 1. Open **Authentik admin panel** > **Providers** > Open your **Vaultwarden provider** - 2. Click **Edit** > Make sure Encryption Key is empty. - 3. **If not empty**: Select -------- in the dropdown. - 4. Make sure not to touch the **Signing Key**, a valid certificate has to be selected - 5. Click **Update** - 6. Retry +#### `Failed to contact token endpoint: Parse(Error ... Invalid JSON web token: found 5 parts`: +This error is probably due to an encrypted token (JWE), ensure that no encryption key is used.\ +Steps: + 1. Open **Authentik admin panel** > **Providers** > Open your **Vaultwarden provider** + 2. Click **Edit** > Make sure Encryption Key is empty. + 3. **If Encryption Key is not empty**: Select `--------` in the dropdown. + 4. Make sure not to touch the **Signing Key**, a valid certificate has to be selected + 5. Click **Update** + 6. Retry ## Casdoor -Since version [v1.639.0](https://github.com/casdoor/casdoor/releases/tag/v1.639.0) should work (Tested with version [v1.686.0](https://github.com/casdoor/casdoor/releases/tag/v1.686.0)). -When creating the application you will need to select the `Token format -> JWT-Standard`. +When creating the application you will need to select the `Token format -> JWT-Standard`. This should work since version [v1.639.0](https://github.com/casdoor/casdoor/releases/tag/v1.639.0). (Tested with version [v1.686.0](https://github.com/casdoor/casdoor/releases/tag/v1.686.0)). Then configure your server with: @@ -183,7 +184,7 @@ Then configure your server with: Create an application in your Gitlab Settings with -- `redirectURI`: https://your.domain/identity/connect/oidc-signin +- `redirectURI`: `https://vaultwarden.example.tld/identity/connect/oidc-signin` - `Confidential`: `true` - `scopes`: `openid`, `profile`, `email` @@ -212,7 +213,7 @@ No special configuration required. Configure your server with : -- `SSO_AUTHORITY=https://your.domain/oauth2/openid/${SSO_CLIENT_ID}` +- `SSO_AUTHORITY=https://{AUTHORITY_DOMAIN}/oauth2/openid/${SSO_CLIENT_ID}` - `SSO_CLIENT_ID` - `SSO_CLIENT_SECRET` @@ -221,7 +222,7 @@ Configure your server with : 1. Create an "App registration" in [Entra ID](https://entra.microsoft.com/) following [Identity | Applications | App registrations](https://entra.microsoft.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade/quickStartType//sourceType/Microsoft_AAD_IAM). 2. From the "Overview" of your "App registration", you'll need the "Directory (tenant) ID" for the `SSO_AUTHORITY` variable and the "Application (client) ID" as the `SSO_CLIENT_ID` value. 3. In "Certificates & Secrets" create an "App secret" , you'll need the "Secret Value" for the `SSO_CLIENT_SECRET` variable. -4. In "Authentication" add as "Web Redirect URI". +4. In "Authentication" add `https://vaultwarden.example.tld/identity/connect/oidc-signin` as "Web Redirect URI". 5. In "API Permissions" make sure you have `profile`, `email` and `offline_access` listed under "API / Permission name" (`offline_access` is required, otherwise no refresh_token is returned, see ). Only the v2 endpoint is compliant with the OpenID spec, see and . @@ -263,7 +264,7 @@ Your configuration should look like this: To obtain a `refresh_token` to be able to extend session you'll need to add the `offline_access` scope. -Additionally Zitadel include the `Project id` and the `Client Id` in the audience of the Id Token. +Additionally Zitadel includes the `Project id` and the `Client Id` in the audience of the Id Token. For the validation to work you will need to add the `Resource Id` as a trusted audience (`Client Id` is trusted by default). You can control the trusted audience with the config `SSO_AUDIENCE_TRUSTED`. @@ -282,10 +283,10 @@ Config will look like: ## Session lifetime -Session lifetime is dependant on refresh token and access token returned after calling your SSO token endpoint (grant type `authorization_code`). +Session lifetime is dependent on refresh token and access token returned after calling your SSO token endpoint (grant type `authorization_code`). If no refresh token is returned then the session will be limited to the access token lifetime. -Tokens are not persisted in the server but wrapped in JWT tokens and returned to the application (The `refresh_token` and `access_token` values returned by VW `identity/connect/token` endpoint). +Tokens are not persisted in the server but wrapped in JWT tokens and returned to the application (The `refresh_token` and `access_token` values returned by Vaultwardens `/identity/connect/token` endpoint). Note that the server will always return a `refresh_token` for compatibility reasons with the web front and it presence does not indicate that a refresh token was returned by your SSO (But you can decode its value with and then check if the `token` field contain anything). With a refresh token present, activity in the application will trigger a refresh of the access token when it's close to expiration ([5min](https://github.com/bitwarden/clients/blob/0bcb45ed5caa990abaff735553a5046e85250f24/libs/common/src/auth/services/token.service.ts#L126) in web client). @@ -303,16 +304,15 @@ Running with `LOG_LEVEL=debug` you'll be able to see information on token expira ## Desktop Client -There is some issue to handle redirection from your browser (used for sso login) to the application. +There is some issue to handle redirection from your browser (used for SSO login) to the application. ### Chrome Some user report having ([issues](https://github.com/bitwarden/clients/issues/12929)). -## Firefox - -On Windows you'll be presented with a prompt the first time you log to confirm which application should be launched (But there is a bug at the moment you might end-up with an empty vault after login atm). +### Firefox +On Windows you'll be presented with a prompt the first time you log to confirm which application should be launched (But there is a bug at the moment you might end-up with an empty vault after login at the moment). On Linux it's a bit more tricky. First you'll need to add some config in `about:config` : @@ -331,4 +331,4 @@ data:text/html,Click me to register Bitwarden ``` From now on the redirection should now work. -If you need to change the application launched you can now find it in `Settings` by using the search function and entering `application`. +If you need to change the application launched you can now find it in `Settings` by using the search function and entering `application`. \ No newline at end of file