diff --git a/docs/admin/users/idp-sync.md b/docs/admin/users/idp-sync.md index 8e9ea79a9a..ee2dc83be3 100644 --- a/docs/admin/users/idp-sync.md +++ b/docs/admin/users/idp-sync.md @@ -1,13 +1,39 @@ -# IDP Sync +# IdP Sync
-IDP sync is an Enterprise and Premium feature. +IdP sync is an Enterprise and Premium feature. [Learn more](https://coder.com/pricing#compare-plans).
+IdP (Identity provider) sync allows you to use OpenID Connect (OIDC) to +synchronize Coder groups, roles, and organizations based on claims from your IdP. + +## Prerequisites + +### Confirm that OIDC provider sends claims + +To confirm that your OIDC provider is sending claims, log in with OIDC and visit +the following URL with an `Owner` account: + +```text +https://[coder.example.com]/api/v2/debug/[your-username]/debug-link +``` + +You should see a field in either `id_token_claims`, `user_info_claims` or +both followed by a list of the user's OIDC groups in the response. + +This is the [claim](https://openid.net/specs/openid-connect-core-1_0.html#Claims) +sent by the OIDC provider. + +Depending on the OIDC provider, this claim might be called something else. +Common names include `groups`, `memberOf`, and `roles`. + +See the [troubleshooting section](#troubleshooting-grouproleorganization-sync) +for help troubleshooting common issues. + ## Group Sync If your OpenID Connect provider supports group claims, you can configure Coder @@ -21,115 +47,36 @@ If group sync is enabled, the user's groups will be controlled by the OIDC provider. This means manual group additions/removals will be overwritten on the next user login. -There are two ways you can configure group sync: +For deployments with multiple [organizations](./organizations.md), configure +group sync for each organization.
-## Server Flags +### Dashboard -1. Confirm that your OIDC provider is sending claims. - - Log in with OIDC and visit the following URL with an `Owner` account: +1. Fetch the corresponding group IDs using the following endpoint: ```text - https://[coder.example.com]/api/v2/debug/[your-username]/debug-link + https://[coder.example.com]/api/v2/groups ``` - You should see a field in either `id_token_claims`, `user_info_claims` or - both followed by a list of the user's OIDC groups in the response. This is - the [claim](https://openid.net/specs/openid-connect-core-1_0.html#Claims) - sent by the OIDC provider. +1. As an Owner or Organization Admin, go to **Admin settings**, select + **Organizations**, then **IdP Sync**: - See [Troubleshooting](#troubleshooting-grouproleorganization-sync) to debug - this. + ![IdP Sync - Group sync settings](../../images/admin/users/organizations/group-sync-empty.png) - Depending on the OIDC provider, this claim may be called something else. - Common names include `groups`, `memberOf`, and `roles`. +1. Enter the **Group sync field** and an optional **Regex filter**, then select + **Save**. -1. Configure the Coder server to read groups from the claim name with the - [OIDC group field](../../reference/cli/server.md#--oidc-group-field) server - flag: +1. Select **Auto create missing groups** to automatically create groups + returned by the OIDC provider if they do not exist in Coder. - - Environment variable: +1. Enter the **IdP group name** and **Coder group**, then **Add IdP group**. - ```sh - CODER_OIDC_GROUP_FIELD=groups - ``` - - - As a flag: - - ```sh - --oidc-group-field groups - ``` - -On login, users will automatically be assigned to groups that have matching -names in Coder and removed from groups that the user no longer belongs to. - -For cases when an OIDC provider only returns group IDs or you want to have -different group names in Coder than in your OIDC provider, you can configure -mapping between the two with the -[OIDC group mapping](../../reference/cli/server.md#--oidc-group-mapping) server -flag: - -- Environment variable: - - ```sh - CODER_OIDC_GROUP_MAPPING='{"myOIDCGroupID": "myCoderGroupName"}' - ``` - -- As a flag: - - ```sh - --oidc-group-mapping '{"myOIDCGroupID": "myCoderGroupName"}' - ``` - -Below is an example mapping in the Coder Helm chart: - -```yaml -coder: - env: - - name: CODER_OIDC_GROUP_MAPPING - value: > - {"myOIDCGroupID": "myCoderGroupName"} -``` - -From the example above, users that belong to the `myOIDCGroupID` group in your -OIDC provider will be added to the `myCoderGroupName` group in Coder. - -## Runtime (Organizations) - -
- -You must have a Premium license with Organizations enabled to use this. -[Contact your account team](https://coder.com/contact) for more details. - -
- -For deployments with multiple [organizations](./organizations.md), you must -configure group sync at the organization level. In future Coder versions, you -will be able to configure this in the UI. For now, you must use CLI commands. +### CLI 1. Confirm you have the [Coder CLI](../../install/index.md) installed and are - logged in with a user who is an Owner or Organization Admin role. - -1. Confirm that your OIDC provider is sending a groups claim. - - Log in with OIDC and visit the following URL: - - ```text - https://[coder.example.com]/api/v2/debug/[your-username]/debug-link - ``` - - You should see a field in either `id_token_claims`, `user_info_claims` or - both followed by a list of the user's OIDC groups in the response. This is - the [claim](https://openid.net/specs/openid-connect-core-1_0.html#Claims) - sent by the OIDC provider. - - See [Troubleshooting](#troubleshooting-grouproleorganization-sync) to debug - this. - - Depending on the OIDC provider, this claim may be called something else. - Common names include `groups`, `memberOf`, and `roles`. + logged in with a user who is an Owner or has an Organization Admin role. 1. To fetch the current group sync settings for an organization, run the following: @@ -165,7 +112,7 @@ Below is an example that uses the `groups` claim and maps all groups prefixed by
-You much specify Coder group IDs instead of group names. The fastest way to find +You must specify Coder group IDs instead of group names. The fastest way to find the ID for a corresponding group is by visiting `https://coder.example.com/api/v2/groups`. @@ -200,7 +147,67 @@ coder organizations settings set group-sync \ Visit the Coder UI to confirm these changes: -![IDP Sync](../../images/admin/users/organizations/group-sync.png) +![IdP Sync](../../images/admin/users/organizations/group-sync.png) + +### Server Flags + +
+ +Use server flags only with Coder deployments with a single organization. + +You can use the dashboard to configure group sync instead. + +
+ +1. Configure the Coder server to read groups from the claim name with the + [OIDC group field](../../reference/cli/server.md#--oidc-group-field) server + flag: + + - Environment variable: + + ```sh + CODER_OIDC_GROUP_FIELD=groups + ``` + + - As a flag: + + ```sh + --oidc-group-field groups + ``` + +1. On login, users will automatically be assigned to groups that have matching + names in Coder and removed from groups that the user no longer belongs to. + +1. For cases when an OIDC provider only returns group IDs or you want to have + different group names in Coder than in your OIDC provider, you can configure + mapping between the two with the + [OIDC group mapping](../../reference/cli/server.md#--oidc-group-mapping) server + flag: + + - Environment variable: + + ```sh + CODER_OIDC_GROUP_MAPPING='{"myOIDCGroupID": "myCoderGroupName"}' + ``` + + - As a flag: + + ```sh + --oidc-group-mapping '{"myOIDCGroupID": "myCoderGroupName"}' + ``` + + Below is an example mapping in the Coder Helm chart: + + ```yaml + coder: + env: + - name: CODER_OIDC_GROUP_MAPPING + value: > + {"myOIDCGroupID": "myCoderGroupName"} + ``` + + From this example, users that belong to the `myOIDCGroupID` group in your + OIDC provider will be added to the `myCoderGroupName` group in Coder.
@@ -214,88 +221,36 @@ Users who are not in a matching group will see the following error: ## Role Sync -
- -Role sync is an Enterprise and Premium feature. -[Learn more](https://coder.com/pricing#compare-plans). - -
- If your OpenID Connect provider supports roles claims, you can configure Coder to synchronize roles in your auth provider to roles within Coder. -There are 2 ways to do role sync. Server Flags assign site wide roles, and -runtime org role sync assigns organization roles - -
- -You must have a Premium license with Organizations enabled to use this. -[Contact your account team](https://coder.com/contact) for more details. - -
+For deployments with multiple [organizations](./organizations.md), configure +role sync at the organization level.
-## Server Flags +### Dashboard -1. Confirm that your OIDC provider is sending a roles claim by logging in with - OIDC and visiting the following URL with an `Owner` account: +1. As an Owner or Organization Admin, go to **Admin settings**, select + **Organizations**, then **IdP Sync**. - ```text - https://[coder.example.com]/api/v2/debug/[your-username]/debug-link - ``` +1. Select the **Role sync settings** tab: - You should see a field in either `id_token_claims`, `user_info_claims` or - both followed by a list of the user's OIDC roles in the response. This is the - [claim](https://openid.net/specs/openid-connect-core-1_0.html#Claims) sent by - the OIDC provider. + ![IdP Sync - Role sync settings](../../images/admin/users/organizations/role-sync-empty.png) - See [Troubleshooting](#troubleshooting-grouproleorganization-sync) to debug - this. +1. Enter the **Role sync field**, then select **Save**. - Depending on the OIDC provider, this claim may be called something else. +1. Enter the **IdP role name** and **Coder role**, then **Add IdP role**. -1. Configure the Coder server to read groups from the claim name with the - [OIDC role field](../../reference/cli/server.md#--oidc-user-role-field) - server flag: + To add a new custom role, select **Roles** from the sidebar, then + **Create custom role**. -1. Set the following in your Coder server [configuration](../setup/index.md). + Visit the [groups and roles documentation](./groups-roles.md) for more information. - ```env - # Depending on your identity provider configuration, you may need to explicitly request a "roles" scope - CODER_OIDC_SCOPES=openid,profile,email,roles +### CLI - # The following fields are required for role sync: - CODER_OIDC_USER_ROLE_FIELD=roles - CODER_OIDC_USER_ROLE_MAPPING='{"TemplateAuthor":["template-admin","user-admin"]}' - ``` - -One role from your identity provider can be mapped to many roles in Coder. The -example above maps to two roles in Coder. - -## Runtime (Organizations) - -For deployments with multiple [organizations](./organizations.md), you can -configure role sync at the organization level. In future Coder versions, you -will be able to configure this in the UI. For now, you must use CLI commands. - -1. Confirm that your OIDC provider is sending a roles claim. - - Log in with OIDC and visit the following URL with an `Owner` account: - - ```text - https://[coder.example.com]/api/v2/debug/[your-username]/debug-link - ``` - - You should see a field in either `id_token_claims`, `user_info_claims` or - both followed by a list of the user's OIDC roles in the response. This is the - [claim](https://openid.net/specs/openid-connect-core-1_0.html#Claims) sent by - the OIDC provider. - - See [Troubleshooting](#troubleshooting-grouproleorganization-sync) to debug - this. - - Depending on the OIDC provider, this claim may be called something else. +1. Confirm you have the [Coder CLI](../../install/index.md) installed and are + logged in with a user who is an Owner or has an Organization Admin role. 1. To fetch the current group sync settings for an organization, run the following: @@ -316,7 +271,7 @@ will be able to configure this in the UI. For now, you must use CLI commands. ``` Below is an example that uses the `roles` claim and maps `coder-admins` from the -IDP as an `Organization Admin` and also maps to a custom `provisioner-admin` +IdP as an `Organization Admin` and also maps to a custom `provisioner-admin` role: ```json @@ -332,7 +287,7 @@ role:
Be sure to use the `name` field for each role, not the display name. Use -`coder organization roles show --org=` to see roles for your +`coder organization roles show --org=` to see roles for your organization.
@@ -347,19 +302,40 @@ coder organizations settings set role-sync \ Visit the Coder UI to confirm these changes: -![IDP Sync](../../images/admin/users/organizations/role-sync.png) +![IdP Sync](../../images/admin/users/organizations/role-sync.png) + +### Server Flags + +
+ +Use server flags only with Coder deployments with a single organization. + +You can use the dashboard to configure role sync instead. + +
+ +1. Configure the Coder server to read groups from the claim name with the + [OIDC role field](../../reference/cli/server.md#--oidc-user-role-field) + server flag: + +1. Set the following in your Coder server [configuration](../setup/index.md). + + ```env + # Depending on your identity provider configuration, you may need to explicitly request a "roles" scope + CODER_OIDC_SCOPES=openid,profile,email,roles + + # The following fields are required for role sync: + CODER_OIDC_USER_ROLE_FIELD=roles + CODER_OIDC_USER_ROLE_MAPPING='{"TemplateAuthor":["template-admin","user-admin"]}' + ``` + +One role from your identity provider can be mapped to many roles in Coder. The +example above maps to two roles in Coder.
## Organization Sync -
- -Organization sync is an Enterprise and Premium feature. -[Learn more](https://coder.com/pricing#compare-plans). - -
- If your OpenID Connect provider supports groups/role claims, you can configure Coder to synchronize claims in your auth provider to organizations within Coder. @@ -370,28 +346,11 @@ Organization sync works across all organizations. On user login, the sync will add and remove the user from organizations based on their IdP claims. After the sync, the user's state should match that of the IdP. -You can initiate an organization sync through the CLI or through the Coder -dashboard: +You can initiate an organization sync through the Coder dashboard or CLI:
-## Dashboard - -1. Confirm that your OIDC provider is sending claims. Log in with OIDC and visit - the following URL with an `Owner` account: - - ```text - https://[coder.example.com]/api/v2/debug/[your-username]/debug-link - ``` - - You should see a field in either `id_token_claims`, `user_info_claims` or - both followed by a list of the user's OIDC groups in the response. This is - the [claim](https://openid.net/specs/openid-connect-core-1_0.html#Claims) - sent by the OIDC provider. See - [Troubleshooting](#troubleshooting-grouproleorganization-sync) to debug this. - - Depending on the OIDC provider, this claim may be called something else. - Common names include `groups`, `memberOf`, and `roles`. +### Dashboard 1. Fetch the corresponding organization IDs using the following endpoint: @@ -400,7 +359,7 @@ dashboard: ``` 1. As a Coder organization user admin or site-wide user admin, go to - **Settings** > **IdP organization sync**. + **Admin settings** > **Deployment** and select **IdP organization sync**. 1. In the **Organization sync field** text box, enter the organization claim, then select **Save**. @@ -415,7 +374,7 @@ dashboard: ![IdP organization sync](../../images/admin/users/organizations/idp-org-sync.png) -## CLI +### CLI Use the Coder CLI to show and adjust the settings. @@ -467,11 +426,11 @@ settings, a user's memberships will update when they log out and log back in. ## Troubleshooting group/role/organization sync -Some common issues when enabling group/role sync. +Some common issues when enabling group, role, or organization sync. ### General guidelines -If you are running into issues with group/role sync: +If you are running into issues with a sync: 1. View your Coder server logs and enable [verbose mode](../../reference/cli/index.md#-v---verbose). @@ -487,7 +446,7 @@ If you are running into issues with group/role sync: 1. Attempt to log in, preferably with a user who has the `Owner` role. -The logs for a successful group sync look like this (human-readable): +The logs for a successful sync look like this (human-readable): ```sh [debu] coderd.userauth: got oidc claims request_id=49e86507-6842-4b0b-94d4-f245e62e49f3 source=id_token claim_fields="[aio aud email exp groups iat idp iss name nbf oid preferred_username rh sub tid uti ver]" blank=[] @@ -552,7 +511,7 @@ The application '' asked for scope 'groups' that doesn't exist This can happen because the identity provider has a different name for the scope. For example, Azure AD uses `GroupMember.Read.All` instead of `groups`. -You can find the correct scope name in the IDP's documentation. Some IDP's allow +You can find the correct scope name in the IdP's documentation. Some IdPs allow configuring the name of this scope. The solution is to update the value of `CODER_OIDC_SCOPES` to the correct value @@ -562,15 +521,15 @@ for the identity provider. Steps to troubleshoot. -1. Ensure the user is a part of a group in the IDP. If the user has 0 groups, no +1. Ensure the user is a part of a group in the IdP. If the user has 0 groups, no `groups` claim will be sent. 2. Check if another claim appears to be the correct claim with a different name. A common name is `memberOf` instead of `groups`. If this is present, update `CODER_OIDC_GROUP_FIELD=memberOf`. -3. Make sure the number of groups being sent is under the limit of the IDP. Some - IDPs will return an error, while others will just omit the `groups` claim. A +3. Make sure the number of groups being sent is under the limit of the IdP. Some + IdPs will return an error, while others will just omit the `groups` claim. A common solution is to create a filter on the identity provider that returns - less than the limit for your IDP. + less than the limit for your IdP. - [Azure AD limit is 200, and omits groups if exceeded.](https://learn.microsoft.com/en-us/azure/active-directory/hybrid/connect/how-to-connect-fed-group-claims#options-for-applications-to-consume-group-information) - [Okta limit is 100, and returns an error if exceeded.](https://developer.okta.com/docs/reference/api/oidc/#scope-dependent-claims-not-always-returned) @@ -582,32 +541,37 @@ Below are some details specific to individual OIDC providers. > **Note:** Tested on ADFS 4.0, Windows Server 2019 -1. In your Federation Server, create a new application group for Coder. Follow - the steps as described - [here.](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/development/msal/adfs-msal-web-app-web-api#app-registration-in-ad-fs) +1. In your Federation Server, create a new application group for Coder. + Follow the steps as described in the [Windows Server documentation] + (https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/development/msal/adfs-msal-web-app-web-api#app-registration-in-ad-fs). + - **Server Application**: Note the Client ID. - **Configure Application Credentials**: Note the Client Secret. - **Configure Web API**: Set the Client ID as the relying party identifier. - **Application Permissions**: Allow access to the claims `openid`, `email`, `profile`, and `allatclaims`. + 1. Visit your ADFS server's `/.well-known/openid-configuration` URL and note the value for `issuer`. - > **Note:** This is usually of the form - > `https://adfs.corp/adfs/.well-known/openid-configuration` + + This will look something like + `https://adfs.corp/adfs/.well-known/openid-configuration`. + 1. In Coder's configuration file (or Helm values as appropriate), set the following environment variables or their corresponding CLI arguments: - - `CODER_OIDC_ISSUER_URL`: the `issuer` value from the previous step. - - `CODER_OIDC_CLIENT_ID`: the Client ID from step 1. - - `CODER_OIDC_CLIENT_SECRET`: the Client Secret from step 1. + - `CODER_OIDC_ISSUER_URL`: `issuer` value from the previous step. + - `CODER_OIDC_CLIENT_ID`: Client ID from step 1. + - `CODER_OIDC_CLIENT_SECRET`: Client Secret from step 1. - `CODER_OIDC_AUTH_URL_PARAMS`: set to - ```console + ```json {"resource":"$CLIENT_ID"} ``` - where `$CLIENT_ID` is the Client ID from step 1 - ([see here](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/overview/ad-fs-openid-connect-oauth-flows-scenarios#:~:text=scope%E2%80%AFopenid.-,resource,-optional)). + Where `$CLIENT_ID` is the Client ID from step 1. + Consult the Microsoft [AD FS OpenID Connect/OAuth flows and Application Scenarios documentation](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/overview/ad-fs-openid-connect-oauth-flows-scenarios#:~:text=scope%E2%80%AFopenid.-,resource,-optional) for more information. + This is required for the upstream OIDC provider to return the requested claims. @@ -615,34 +579,35 @@ Below are some details specific to individual OIDC providers. 1. Configure [Issuance Transform Rules](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-rule-to-send-ldap-attributes-as-claims) - on your federation server to send the following claims: + on your Federation Server to send the following claims: - `preferred_username`: You can use e.g. "Display Name" as required. - `email`: You can use e.g. the LDAP attribute "E-Mail-Addresses" as required. - `email_verified`: Create a custom claim rule: - ```console + ```json => issue(Type = "email_verified", Value = "true") ``` - (Optional) If using Group Sync, send the required groups in the configured - groups claim field. See [here](https://stackoverflow.com/a/55570286) for an - example. + groups claim field. + Use [this answer from Stack Overflow](https://stackoverflow.com/a/55570286) for an example. ### Keycloak -The access_type parameter has two possible values: "online" and "offline." By -default, the value is set to "offline". This means that when a user -authenticates using OIDC, the application requests offline access to the user's -resources, including the ability to refresh access tokens without requiring the -user to reauthenticate. +The `access_type` parameter has two possible values: `online` and `offline`. +By default, the value is set to `offline`. -To enable the `offline_access` scope, which allows for the refresh token +This means that when a user authenticates using OIDC, the application requests +offline access to the user's resources, including the ability to refresh access +tokens without requiring the user to reauthenticate. + +To enable the `offline_access` scope which allows for the refresh token functionality, you need to add it to the list of requested scopes during the -authentication flow. Including the `offline_access` scope in the requested -scopes ensures that the user is granted the necessary permissions to obtain -refresh tokens. +authentication flow. +Including the `offline_access` scope in the requested scopes ensures that the +user is granted the necessary permissions to obtain refresh tokens. By combining the `{"access_type":"offline"}` parameter in the OIDC Auth URL with the `offline_access` scope, you can achieve the desired behavior of obtaining diff --git a/docs/images/admin/users/organizations/group-sync-empty.png b/docs/images/admin/users/organizations/group-sync-empty.png new file mode 100644 index 0000000000..4114ec7cac Binary files /dev/null and b/docs/images/admin/users/organizations/group-sync-empty.png differ diff --git a/docs/images/admin/users/organizations/group-sync.png b/docs/images/admin/users/organizations/group-sync.png index a4013f2f15..f617dd02ee 100644 Binary files a/docs/images/admin/users/organizations/group-sync.png and b/docs/images/admin/users/organizations/group-sync.png differ diff --git a/docs/images/admin/users/organizations/role-sync-empty.png b/docs/images/admin/users/organizations/role-sync-empty.png new file mode 100644 index 0000000000..91e36fff5b Binary files /dev/null and b/docs/images/admin/users/organizations/role-sync-empty.png differ diff --git a/docs/images/admin/users/organizations/role-sync.png b/docs/images/admin/users/organizations/role-sync.png index 1b0fafb39f..9360c9e133 100644 Binary files a/docs/images/admin/users/organizations/role-sync.png and b/docs/images/admin/users/organizations/role-sync.png differ diff --git a/docs/images/admin/users/organizations/template-org-picker.png b/docs/images/admin/users/organizations/template-org-picker.png index 73c37ed517..cf5d807619 100644 Binary files a/docs/images/admin/users/organizations/template-org-picker.png and b/docs/images/admin/users/organizations/template-org-picker.png differ diff --git a/docs/images/admin/users/organizations/workspace-list.png b/docs/images/admin/users/organizations/workspace-list.png index bbe6cca9eb..e007cdaf87 100644 Binary files a/docs/images/admin/users/organizations/workspace-list.png and b/docs/images/admin/users/organizations/workspace-list.png differ diff --git a/docs/manifest.json b/docs/manifest.json index 7cf556984e..119099ab0b 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -284,7 +284,7 @@ "state": ["enterprise", "premium"] }, { - "title": "IDP Sync", + "title": "IdP Sync", "path": "./admin/users/idp-sync.md", "state": ["enterprise", "premium"] }, diff --git a/docs/tutorials/best-practices/organizations.md b/docs/tutorials/best-practices/organizations.md index 473bf832e1..5771df3e0b 100644 --- a/docs/tutorials/best-practices/organizations.md +++ b/docs/tutorials/best-practices/organizations.md @@ -94,17 +94,6 @@ provider such as Okta. A single claim from the identity provider (like `memberOf`) can be used to sync site-wide roles, organizations, groups, and organization roles. -### Planned enhancements - -Site-wide role sync is managed via server flags. We plan on changing this to -runtime configuration so Coder does not need a re-deploy: - -- Issue [coder/internal#86](https://github.com/coder/internal/issues/86) - -Make all sync configurable via the dashboard UI: - -- [coder/coder#15290](https://github.com/coder/coder/issues/15290) - Regex filters and mapping can be configured to ensure the proper resources are allocated in Coder. Learn more about [IDP sync](../../admin/users/idp-sync.md).