IdP Sync

Enterprise
Premium

IdP sync is an Enterprise and Premium feature. Learn more.

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:

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 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 for help troubleshooting common issues.

Group Sync

If your OpenID Connect provider supports group claims, you can configure Coder to synchronize groups in your auth provider to groups within Coder. To enable group sync, ensure that the groups claim is being sent by your OpenID provider. You might need to request an additional scope or additional configuration on the OpenID provider side.

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.

For deployments with multiple organizations, configure group sync for each organization.

Group allowlist

You can limit which groups from your identity provider can log in to Coder with CODER_OIDC_ALLOWED_GROUPS. Users who are not in a matching group will see the following error:

Unauthorized group error

Role Sync

If your OpenID Connect provider supports roles claims, you can configure Coder to synchronize roles in your auth provider to roles within Coder.

For deployments with multiple organizations, configure role sync at the organization level.

Organization Sync

If your OpenID Connect provider supports groups/role claims, you can configure Coder to synchronize claims in your auth provider to organizations within Coder.

Viewing and editing the organization settings requires deployment admin permissions (UserAdmin or Owner).

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 Coder dashboard or CLI:

Troubleshooting group/role/organization sync

Some common issues when enabling group, role, or organization sync.

General guidelines

If you are running into issues with a sync:

  1. View your Coder server logs and enable verbose mode.

  2. To reduce noise, you can filter for only logs related to group/role sync:

    CODER_VERBOSE=true
    CODER_LOG_FILTER=".*userauth.*|.*groups returned.*"
    
  3. Restart the server after changing these configuration values.

  4. Attempt to log in, preferably with a user who has the Owner role.

The logs for a successful sync look like this (human-readable):

[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=[]

[debu]  coderd.userauth: got oidc claims  request_id=49e86507-6842-4b0b-94d4-f245e62e49f3  source=userinfo  claim_fields="[email family_name given_name name picture sub]"  blank=[]

[debu]  coderd.userauth: got oidc claims  request_id=49e86507-6842-4b0b-94d4-f245e62e49f3  source=merged  claim_fields="[aio aud email exp family_name given_name groups iat idp iss name nbf oid picture preferred_username rh sub tid uti ver]"  blank=[]

[debu]  coderd: groups returned in oidc claims  request_id=49e86507-6842-4b0b-94d4-f245e62e49f3  [email protected]  username=ben  len=3  groups="[c8048e91-f5c3-47e5-9693-834de84034ad 66ad2cc3-a42f-4574-a281-40d1922e5b65 70b48175-107b-4ad8-b405-4d888a1c466f]"

To view the full claim, the Owner role can visit this endpoint on their Coder deployment after logging in:

https://[coder.example.com]/api/v2/debug/[username]/debug-link

User not being assigned / Group does not exist

If you want Coder to create groups that do not exist, you can set the following environment variable.

If you enable this, your OIDC provider might be sending over many unnecessary groups. Use filtering options on the OIDC provider to limit the groups sent over to prevent creating excess groups.

# as an environment variable
CODER_OIDC_GROUP_AUTO_CREATE=true
# as a flag
--oidc-group-auto-create=true

A basic regex filtering option on the Coder side is available. This is applied after the group mapping (CODER_OIDC_GROUP_MAPPING), meaning if the group is remapped, the remapped value is tested in the regex. This is useful if you want to filter out groups that do not match a certain pattern. For example, if you want to only allow groups that start with my-group- to be created, you can set the following environment variable.

# as an environment variable
CODER_OIDC_GROUP_REGEX_FILTER="^my-group-.*$"
# as a flag
--oidc-group-regex-filter="^my-group-.*$"

Invalid Scope

If you see an error like the following, you may have an invalid scope.

The application '<oidc_application>' asked for scope 'groups' that doesn't exist on the resource...

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 IdPs allow configuring the name of this scope.

The solution is to update the value of CODER_OIDC_SCOPES to the correct value for the identity provider.

No group claim in the got oidc claims log

Steps to troubleshoot.

  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 common solution is to create a filter on the identity provider that returns less than the limit for your IdP.

Provider-Specific Guides

Below are some details specific to individual OIDC providers.

Active Directory Federation Services (ADFS)

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 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.
  2. Visit your ADFS server's /.well-known/openid-configuration URL and note the value for issuer.

    This will look something like https://adfs.corp/adfs/.well-known/openid-configuration.

  3. In Coder's configuration file (or Helm values as appropriate), set the following environment variables or their corresponding CLI arguments:

    • 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

      {"resource":"$CLIENT_ID"}
      

      Where $CLIENT_ID is the Client ID from step 1. Consult the Microsoft AD FS OpenID Connect/OAuth flows and Application Scenarios documentation for more information.

      This is required for the upstream OIDC provider to return the requested claims.

    • CODER_OIDC_IGNORE_USERINFO: Set to true.

  4. Configure Issuance Transform Rules 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:

      => issue(Type = "email_verified", Value = "true")
      
    • (Optional) If using Group Sync, send the required groups in the configured groups claim field. Use this answer from Stack Overflow 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.

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.

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 refresh tokens for offline access to the user's resources.

See an opportunity to improve our docs? Make an edit.