Configuring an OIDC authentication provider

Configuring an OIDC provider

To configure an OIDC (OpenID Connect) provider, create a configuration for connection to an OIDC server and user attribute mapping.

Authentication

  1. The user selects an OIDC provider on the log in page.
  2. The system redirects the user to the OIDC provider's authentication page.
  3. Once the authentication is successful, the OIDC provider redirects the user back to the system, the {UI_APP_ENDPOINT}/auth/callback/oidc endpoint, providing them with the authorization code.
  4. The system exchanges the authorization code for access tokens and an ID token.
  5. The system requests additional information through the userinfo endpoint.
  6. The system creates or updates the user in the database, assigns roles and groups based on information from userinfo.
  7. The system creates a session for the user and redirects them to the home page.

Main configuration parameters

{
    slug: 'keycloak',                  // Unique provider ID
    title: 'Keycloak',                 // Displayed provider name
    type: 'oidc',                      // Provider type (use 'oidc')
    defaultRole: 'datalens.visitor',   // Default role for new users
    config: {
        // OIDC server connection parameters
        issuer: 'https://keycloak.example.org/realms/datalens-enterprise/.well-known/openid-configuration',  // OIDC server URL
        clientId: 'datalens',          // Client ID
        clientSecret: 'password',      // Client secret
        codeChallengeMethod: 'S256',   // PKCE (Proof Key for Code Exchange) method
        scope: ['openid', 'profile', 'email', 'roles', 'groups'],  // Requested access scope
        
        // User attribute mapping (optional)
        userAttributes: {
            userId: 'sub',             // User ID attribute ('sub' by default)
            login: 'preferred_username', // User login attribute ('preferred_username' by default)
            email: 'email',       // User email address attribute ('email' by default)
            firstName: 'given_name',   // User first name attribute ('given_name' by default).
            lastName: 'family_name',   // User last name attribute ('family_name' by default).
        },
        
        // Role settings (optional)
        roles: {
            path: 'resource_access.datalens.roles',  // Path to the roles in `userinfo`
            targetType: 'array-of-strings',          // Role data type
            mapping: {
                'datalens.admin': 'client.datalens.admin',     // Role mapping
                'datalens.creator': 'client.datalens.creator', // Role mapping
                'datalens.visitor': 'client.datalens.visitor', // Role mapping
            },
        },
        syncUserRoles: true,           // Synchronizing user roles at each log-in
        
        // Group settings (optional)
        groups: {
            path: 'groups',            // Path to groups in `userinfo`
            targetType: 'array-of-objects',  // Group data type
            mapping: {                 // Group attribute mapping (only for 'array-of-objects')
                groupId: 'id',         // Group ID attribute
                title: 'name',         // Group name attribute
            },
        },
        syncUserGroups: true,          // Synchronizing user groups at each log-in
    }
}

Detailed description of parameters

Basic parameters

  • slug: Unique provider ID used in URLs and internal IDs.
  • title: Provider name displayed in the interface.
  • type: Provider type; for OIDC, use oidc.
  • defaultRole: Role assigned to the user if unable to define a role from userinfo.

OIDC server connection parameters

  • issuer: URL of the OIDC server providing the OpenID Connect metadata. Usually, this is a URL containing the path to .well-known/openid-configuration.
  • clientId: Client ID received when registering the app in the OIDC provider.
  • clientSecret: Client secret received when registering the app in the OIDC provider.
  • codeChallengeMethod: PKCE (Proof Key for Code Exchange) method against authorization code hijacking attacks. The default value is S256. If set to null, the authorization will use state and nonce without PKCE.
  • scope: Array of requested access scopes. The default value is ['openid', 'profile', 'email'].

User attribute mapping

Use these parameters to set up the mapping between the OIDC user attributes and the user's fields in the system:

  • userId: User ID attribute (sub by default).
  • login: User login attribute (preferred_username by default).
  • email: User email address attribute (email by default).
  • firstName: User first name attribute (given_name by default).
  • lastName: User last name attribute (family_name by default).

Role settings

Use these parameters to configure fetching and mapping user roles from userinfo:

  • path: Path to the roles in userinfo, e.g., resource_access.datalens.roles or realm_access.roles.

  • targetType: Role data type. The possible values are:

    • array-of-strings: Array of strings.
    • stringified-array-of-strings: String containing a serialized JSON array of strings.
  • mapping: Object that maps roles in the system with those in userinfo.

Group settings

Use these parameters to configure fetching and mapping user groups from userinfo:

  • path: Path to groups in userinfo, e.g., groups.

  • targetType: Group data type. The possible values are:

    • array-of-strings: Array of strings, where each string is a group ID.
    • array-of-strings-with-id: Array of strings, each string in id:title format.
    • array-of-objects: Array of objects, each containing the group ID and name.
    • stringified-array-of-strings: String containing a serialized JSON array of strings.
    • stringified-array-of-strings-with-id: String containing a serialized JSON array of strings in id:title format.
    • stringified-array-of-objects: String containing a serialized JSON array of objects.
  • mapping: Object defining which fields in a group object should be used as group ID and name. For array-of-objects or stringified-array-of-objects type, this is a required setting.

    • groupId: Group object field used as its ID.
    • title: Group object field used as its name.

Additional settings

  • syncUserRoles: When set to true (default value), user roles will be synchronized at each log-in.
  • syncUserGroups: When set to true (default value is false), user groups will be synchronized at each log-in.

Features of synchronization between roles and groups

User roles and groups are synchronized the moment the user logs in to the system. If userinfo includes roles and/or groups specified in the configuration, the system will assign them to the user. If no roles are found, the user will be assigned the default role.

Example of a Keycloak configuration

const keycloakConfig = {
    slug: 'keycloak',
    title: 'Keycloak',
    type: 'oidc',
    defaultRole: 'datalens.visitor',
    config: {
        issuer: 'https://keycloak.example.org/realms/datalens-enterprise/.well-known/openid-configuration',
        clientId: 'datalens',
        clientSecret: 'password',
        codeChallengeMethod: 'S256',
        scope: ['openid', 'profile', 'email', 'roles', 'groups'],
        
        roles: {
            path: 'resource_access.datalens.roles',
            targetType: 'array-of-strings',
            mapping: {
                'datalens.admin': 'client.datalens.admin',
                'datalens.creator': 'client.datalens.creator',
            },
        },
        syncUserRoles: true,
        
        groups: {
            path: 'groups',
            targetType: 'array-of-strings', // We recommend that you configure Script Mapper and use 'array-of-objects' to specify the group ID and name
        },
        syncUserGroups: true,
    },
};

Keycloak client settings

Set up a Keycloak client configuration for this example:

  1. Specify the client settings by clicking Clients → your client (datalens) → Settings:

    • Valid redirect URIs: {UI_APP_ENDPOINT}/auth/callback/oidc. Replace UI_APP_ENDPOINT with your app URL, such as http://example.com:8080/auth/callback/oidc.

    • Client authentication: on.

    • Authentication flow: Standard flow.

  2. To create roles, click Clients → your client (datalens) → Roles:

    • client.datalens.admin
    • client.datalens.creator
  3. To create a group, click GroupsCreate group.

  4. To assign a group and roles to a user, click Usersuser.

    • Assign the roles on the Role mapping tab.
    • Assign the roles on the Groups tab.
  5. To set the client scope, click Client scopesCreate client scope.

    • Create the groups scope and Group Membership mapper type. Enable Add to userinfo in the Keycloak settings.
    • Create the roles scope or client roles predefined mapper. Enable Add to userinfo in the Keycloak settings.

Example of userinfo for Keycloak

{
  "sub": "4d2b6d80-49cf-44fb-94c6-946393dea8c7",
  "resource_access": {
    "datalens": {
      "roles": [
        "client.datalens.creator"
      ]
    },
  },
  "email_verified": true,
  "name": "Bob Smith",
  "groups": [
    "datalens-admin"
  ],
  "preferred_username": "bob",
  "given_name": "Bob",
  "family_name": "Smith",
  "email": "bob@example.org"
}

Using a configuration

Configuration via the AUTH_PROVIDERS_CONFIG environment variable

To configure authentication providers, the application uses the AUTH_PROVIDERS_CONFIG environment variable. This variable contains a JSON string with an array of configurations of all authentication providers.

Example of the AUTH_PROVIDERS_CONFIG environment variable:

[
  {
    "slug": "keycloak",
    "title": "Keycloak",
    "type": "oidc",
    "defaultRole": "datalens.visitor",
    "config": {
      "issuer": "https://keycloak.example.org/realms/datalens-enterprise/.well-known/openid-configuration",
      "clientId": "datalens",
      "clientSecret": "password",
      "codeChallengeMethod": "S256",
      "scope": ["openid", "profile", "email", "roles", "groups"],
      "roles": {
        "path": "resource_access.datalens.roles",
        "targetType": "array-of-strings",
        "mapping": {
          "datalens.admin": "client.datalens.admin",
          "datalens.creator": "client.datalens.creator"
        }
      },
      "syncUserRoles": true,
      "groups": {
        "path": "groups",
        "targetType": "array-of-strings"
      },
      "syncUserGroups": true
    }
  }
]