C3 AI Documentation Home

Authentication Using OpenID Connect

OpenID Connect (OIDC) is an identity layer built on top of the OAuth 2.0 authorization protocol. OIDC allows clients to verify the identity of an end-user based on the authentication performed by an authorization server. Using the built-in support for OIDC in the C3 Agentic AI Platform, you can configure a AppUrl to authenticate users through an integration with any valid OpenID Provider.

In redirect authentication flow and direct authentication, it is possible to use either the C3 Agentic AI Platform or the Identity Provider (IdP) as the source of truth for role-based access control. Each of these two scenarios is described in more detail below.

Configuring an OpenID Connect integration

The steps for configuring an OpenID Connect integration are as follows:

  1. Identify an OpenID Provider: The first step is to identify an OpenID Provider (OP), also known as an authorization server, that you want to use for authentication. Examples of OpenID Providers include identity platforms such as Okta, Auth0, and Google.

  2. Register Your Application with the OpenID Provider: Before proceeding to set an OiDC configuration in the C3 AI Platform, you need to register your application with the OpenID Provider. As part of this registration, you typically need to provide a redirect URI that the OpenID Provider can use to send the user's information to your application. In return, you'll receive a client ID and client secret. After you have registered the application in the IdP, make note of the following:

    • The clientId generated by the IdP when the OpenID Connect application was created.
    • The URL for the OpenID Connect discovery metadata document associated with the OiDC application.
  3. Configure Your Application: Next, you need to configure your application with the details of the OpenID Provider. This involves specifying the authorization endpoint, token endpoint, and user information endpoint of the OpenID Provider, and also the client ID and client secret you received when you registered your application.

Run the following commands from the C3 AI Console in the desired application. Note that the OidcIdpConfig#importFromDiscoveryUrl method requires C3.ClusterAdmin permissions:

JavaScript
// Application name
var applicationName = "<name of your application>";
// Application host / App Url
var hostname = "<your host name>";
// Application discovery end point / openid configuration endpoint
var discoveryEndPoint = "<openid configuration endpoint>";
var uri = "https://${hostname}/${applicationName}/oidc/login";
var issuer = "<your issuer>"
var audiences = Array.of("<your audiences>")
// Creates the openid client
var client = OidcIdpClient.make({
    clientId:"<client ID generated from the IdP>",
    redirectUri:uri
});
// Prepares OidcIdpConfig automatically from a discovery end point
var config = OidcIdpConfig.importFromDiscoveryUrl(hostname, discoveryEndPoint, client, "form_post");
OidcIdpConfig.forId(hostname).setConfigValue("defaultGroupId", "dev");
OidcIdpConfig.forId(hostname).setConfigValue("trustedApplicationHosts", Array.of(hostname));
OidcIdpConfig.forId(hostname).setConfigValue("jitUserCreation", true);
OidcIdpConfig.forId(hostname).setConfigValue("scopes", Array.of("openid", "email", "profile"));
OidcIdpConfig.forId(hostname).setConfigValue("issuer", issuer).setConfig("CLUSTER");
OidcIdpConfig.forId(hostname).setConfigValue("audiences", audiences).setConfig("CLUSTER");
UserGroup.forId("C3.AppAdmin").addIdpGroupForIdp(OidcIdpConfig.forId(hostname), "dev")

Note: When configuring at the cluster level, refer to the Prerequisites for C3 Agentic AI Platform Integration with Identity Providers topic for more details.

Please refer to the Config Type for all configurations.

Note: The C3 Agentic AI Platform supports both the implicit flow and the authorization code flows. The implicit flow redirects users to the configured identity provider's single sign-on experience.

After applying the configuration, validate the redirect flow:

  • Start a private browsing session or clear your browser cookies.
  • Navigate to the app URL that you configured for OpenID Connect authentication.
  • Confirm that you are redirected to the OpenID Provider's single sign-on experience.
  1. Request User's Identity: In your application, you need to redirect users to the OpenID Provider's authorization endpoint when they want to log in. After the user logs in, the OpenID Provider redirects users back to your application with an ID token.

  2. Verify ID Token: Your application needs to verify the ID token returned by the OpenID Provider. This includes checking the signature to ensure the token was issued by the expected OpenID Provider and has not been tampered with, as well as checking the claims within the token to ensure they contain the expected values.

  3. Retrieve User Info: After the ID token is verified, you can extract the user's information from the token or optionally make a separate request to the OpenID Provider's user information endpoint to retrieve additional user information.

  4. User Session Management: Finally, you'll need to handle session management for the authenticated user within your application, including setting up a session, refreshing tokens if needed, and handling logout requests.

These steps can vary depending on the specifics of your application and the OpenID Provider you are using, but this provides a general high-level overview of the process. Refer to the specific OpenID Provider's documentation for detailed instructions.

Configure custom fields on an OidcIdToken

The C3 Agentic AI Platform supports custom group names, roles, and other fields on the OidcIdToken Type. To configure a custom field on the OidcIdToken, update the IdP configuration with the field you want to set.

For example, if your OidcIdToken calls your groups claim as actiongroups, run the following code to update the IdP configuration to support the group claim name actiongroups:

JavaScript
OidcIdpConfig.forId(idpConfigId).withClaimNames(OidcIdToken.ClaimNames.make().withGroups("actiongroups")).setConfig()

If you have a different claim name for roles called occupations, run the following code to update the IdP configuration to support the roles claim name occupations:

JavaScript
OidcIdpConfig.forId(idpConfigId).withClaimNames(OidcIdToken.ClaimNames.make().withRoles("occupations")).setConfig()

C3 Agentic AI Platform as the source of truth

In this scenario, user permissions are assigned in the C3 Agentic AI Platform directly, either through the C3 AI Console or an application UI. No additional configuration is required to support this by default; however, you must ensure that your IdP is not configured to pass a Role's claim value in the id_token or access_token used to authenticate the user or authorize the request. If the Role's claim is present, then the C3 Agentic AI Platform can assume that Roles are maintained in the IdP, which would override any Role assignments maintained in the platform.

When using the C3 Agentic AI Platform as the source of truth for role-based access control, it is not possible for an administrator to assign users to a set of roles until their user identity has been created during first-time authentication. This is because the id_token, which is created by the IdP, contains the information on how to uniquely identify the user, and the platform is not aware of this information until it encounters the id_token. To help work around this limitation, it is possible (but not required) to add users into a default access role, which is assigned when the user's identity is created for the first time. Run the following to apply this configuration:

JavaScript
var defaultGroupId = 'MyApp.DefaultAccess';
OidcIdpConfig.make(appUrlId).setConfigValue('defaultGroupId', defaultGroupId, ConfigOverride.APP);

This ensures that whenever a new user authenticates for the first time, the user can by default have the MyApp.DefaultAccess role assignments.

IdP as the source of truth

In this scenario, users can be added to IdP groups, and their group assignments are passed to the platform whenever that user authenticates or makes an API request to a platform resource. A user's role assignments are passed to the C3 AI Platform each time the user is authenticated or makes an API request to a platform resource. For an admin role assignment to be resolved, the admin role must also exist in the C3 Agentic AI Platform.

The C3 Agentic AI Platform does not require you to use a specific Identity and Access Management provider. The instructions below use Okta for demonstrative purpose only. To enable the IdP to be the source of truth, the following configurations must be made:

  1. Ensure that all required roles exist in the environments and applications where users can authenticate with OIDC.
  2. Create the corresponding roles in the third-party identity management service (such as Okta) by following the naming convention: clusterId/environment/application/groupName
    • Note that a distinct role must be created for each environment and application where users can be authenticating, for example, prod-myc3cluster/myApp/dev/C3.Developer
    • The appropriate clusterId value can be found with the Cluster.inst() command, run from the /console of that environment
  3. Assign users to the roles in the third-party identity management service as required by your use case, and ensure that those users/groups have been added to the OpenID Connect application in the third-party identity management service
  4. Configure the Okta Org Authorization Server to pass groups in the id_token during redirect authentication
  5. If required by your use case, configure the Custom Authorization Server to pass groups in the access_token for direct request authorization

When this configuration has been applied, the decoded id_token can look something like this:

JSON
{
  "sub": "00u1t28sghq4E23J89sl",
  "name": "Joe Blogs",
  "locale": "en_US",
  "email": "joe@blogs.com",
  "ver": 1,
  "iss": "<company/org okta url>",
  "aud": "0aslwb2012l3J2LoweE2",
  "iat": 1644450075,
  "exp": 1644453675,
  "jti": "ID._mSOIRNBiAieriuagoSOgroAEOENodoalWU",
  "amr": [
    "pwd"
  ],
  "idp": "00salZXLeowlAE392",
  "nonce": "5c80a3073a20f4a3",
  "preferred_username": "joe@blogs.com",
  "given_name": "Joe",
  "family_name": "Blogs",
  "zoneinfo": "America/Los_Angeles",
  "updated_at": 1644444327,
  "email_verified": true,
  "auth_time": 1644450074,
  "groups": [
    "myc3cluster/myEnv/myApp/C3.Developer",
    "SomeOtherOktaGroup"
  ]
}

In this example, the C3 Agentic AI Platform determines this user is a member of the C3.Developer admin role in the myApp:dev application and MyApp.QA admin role in the myApp:stage application of the prod-myc3cluster cluster. The user is authorized to perform any actions that are authorized by these roles. The platform ignores SomeOtherOktaGroup because there is no corresponding admin role.

Each time a user authenticates or an API request is made on behalf of the user by passing the access_token as a bearer token, the role's claim is processed and the user's admin role permissions are updated accordingly. This allows a user administrator to add or remove users from roles in the IdP, and have those role assignments reflected in the C3 AI Platform.

When using this feature, keep in mind the following best practices:

  • When a user's roles are changed in the IdP, the administrator should log that user out from the IdP. This way, when the user re-authenticates, the latest roles mapping can be reflected.
  • Okta only permits a maximum of 100 roles to be passed using the roles claim. This causes authentication problems if a user belongs to many Okta roles. Please make sure that you are using a filter regex similar to cluster_id\/env_name\/app_name\/* when configuring the Okta or custom authorization server to pass a roles claim in the JWT.
  • Two-way integration with the IdP is not supported out-of-the-box at this time. This means that if a role assignment is added for a user directly in the C3 Agentic AI Platform, then this role assignment does not flow back into the IdP by default. The user can be authorized into the new role until they are forced to re-authenticate. At this time, the user's admin role assignments are overridden by whatever roles are passed from the IdP.

When you create a role in the IdP, the C3 Agentic AI Platform permits the naming convention to map non-standard IdP group names to the roles you define within the C3 Agentic AI Platform. This flexibility is crucial for organizations, where Active Directory (AD), for instance, serves as the primary source of truth for identity and access management, with Okta being synchronized with AD to leverage its robust authentication and authorization capabilities.

Consider a company, XYZ, that encounters a challenge while attempting to align their role-naming convention with the one prescribed #2 above. The standard format suggested — clusterId/environment/application/groupName — can clash with company XYZ's internal policies for several reasons:

  • AD, the cornerstone of XYZ's identity management infrastructure, does not permit the use of forward slashes ("/") in naming.
  • There is a strict limit on the character length of names in AD, a maximum at 64 characters.

Such constraints render the C3 Agentic AI Platform's recommended naming convention impractical for company XYZ.

There is a more adaptable approach to role naming and mapping.

The C3 Agentic AI Platform's API exposes a method to explicitly map company XYZ's IdP group names to the corresponding roles within the C3 Agentic AI Platform.

The key to this approach is the use of the following API call:

JavaScript
UserGroup.forId("RoleName").addIdpGroupForIdp(OidcIdpConfig.forId("cluster"), "Non-standard IDP group")

The code snippet above allows for the direct association of an IdP group with a C3 Agentic AI Platform role, bypassing the need for adherence to the standard naming convention and accommodating company XYZ's unique constraints.

Naming convention

To illustrate, let's consider a practical application of this solution within the context of company XYZ:

  • Cluster Identifier: ai.c3.xyz.com

  • Role Name in C3 AI: XYZ.Role.ViewOnly

  • XYZ's IdP Group Claim: APP-C3AI-ViewOnly-CreditFacilityRiskRating

Using the alternative method, XYZ is able to map their specific IdP group claim directly to the role within the C3 AI Platform, irrespective of the naming convention and character limitations that previously posed a barrier. The API call for this mapping would look something like this:

JavaScript
UserGroup.forId("XYZ.Role.ViewOnly").addIdpGroupForIdp(OidcIdpConfig.forId("ai.c3.xyz.com"), "APP-C3AI-ViewOnly-CreditFacilityRiskRating");

Oidc Direct Login

If Oidc Direct Login is enabled, then the user can directly log in to the C3 Agentic AI Platform using the access_token from the IdP.

JavaScript
OidcIdpConfig.make(appUrlId).setConfigValue('directLogin', true, ConfigOverride.APP);

The access_token is used to authenticate the user and authorize the request, and is passed to the C3 AI Platform as a bearer token in the Authorization header of the request:

JSON
{"Authorization": "Bearer <access_token>"}

Authentication using this method will treat IdP as the source of truth for role-based access control, and should only be enabled on the ConfigOverride level.

Removing an OpenID Connect configuration

To remove the OpenID connect configuration for the apps URL, use the following command:

JavaScript
OidcIdpConfig.make(appUrlId).clearConfigAndSecretAllOverrides();

Refer to the Overview of the C3 AI Configuration Framework for more information about the Type Config.

See also

Was this page helpful?