C3 AI Documentation Home

Build an OAuth Token API for your Application

Generate an Open Authorization (OAuth) access token for a client application by building an OAuth token API. By reading through the code snippets and explanations in this topic, you can also gain an understanding of how to handle OAuth operations within the C3 AI environment.

Note: It is important that you first familiarize yourself with concepts in the Authorizing with OAuth topic.

The following example application provides a structured and practical approach to obtaining an OAuth token using the Client Credentials grant type.

Here is the application package file, the specified Types, and their corresponding JavaScript implementations:

  • oauthPlaygroundPackage.c3pkg.json: Defines the application package, detailing its name, dependencies, and purpose.

  • OauthPlayground.c3typ: This file defines the main OauthPlayground Type, responsible for updating OAuth configurations and fetching application IDs based on OAuth application names.

  • OauthPlayground.js: This file contains the core function implementation to manage OAuth configurations and retrieve OAuth application IDs using application names.

  • ClientCredentials.c3typ: This file describes the ClientCredentials Type, designed to handle the Client Credentials grant type for fetching and generating OAuth tokens.

  • ClientCredentials.js: Contains functions that fetch and generate OAuth tokens using the Client Credentials grant type.

Create application package

This is the package for the OAuth application.

Name you package file: oauthPlaygroundPackage.c3pkg.json.

JSON
{
  "name": "oauthPlaygroundPackage",
  "description": "A package to test generating an access token"
}

For more information on the organization and structure of a package, see Package Management Overview.

Define application configuration

You must configure applications using the OAuth 2.0 Authorization Framework in the C3 Agentic AI Platform as an OAuth application.

In the C3 AI Console, define the application's configuration:

JavaScript
var oAuthApp = OAuthApplication.make({
    "name": "demoOAuthApp",
    "redirectUri": "https://test.c3.ai/oauth/callback",
    "homePageUrl": "https://test.c3.ai"
});

This prepares an application configuration with the following parameters:

  • name: Field identifies the application uniquely within the platform or OAuth server.

  • redirectUri: The property sets the URI where the OAuth server sends the user after the application's request for authorization is approved or denied. The URI typically includes a code that the application exchanges for an access token.

  • homePageUrl: This property sets the application's homepage URL. It could be a URL where users can learn more about the application or can be directed to in case of errors or more info needs.

Register application

Registering an OAuth application provides essential information about your application to the authorization server. Registration lets the authorization server verify the application identity and ensures that only trusted applications can request access.

In the C3 AI Console, register the client application with the C3 Agentic AI Platform:

JavaScript
var groups = ["<list of valid groups>"]
var appCredentials = oAuthApp.register(groups);

After client registration, the authorization server generates credentials for that application.

Registering the application returns an instance of the OAuthApplicationCredentials. Here's an example of the returned appCredentials:

JSON
{
  "clientId" : "peegkCHqTumSpb2PHwoyxw",
  "clientSecret" : "q2QoWhzWTk-hFldB4NB6dQ"
}

The clientId and clientSecret are generated when calling the register function on the OAuthApplication. The clientId uniquely identifies the client application in the C3 Agentic AI Platform. The clientSecret is a confidential value used to authenticate the client application to the authorization server. These credentials are crucial for the application to participate in OAuth flows, including obtaining tokens.

Note: You can also deregister your OAuth application by using the following example in the C3 AI Console.

JavaScript
OAuthApplication.forId('<id of the OAuthApplication obj you want to deregister>').deregister()

Set up utility functions

In this example, OauthPlayground.c3typ provides utility functions for handling OAuth operations. The functions enable developers to configure OAuth settings and retrieve OAuth application IDs.

Type
entity type OauthPlayground {

  /**
   * Updates the OAuth configuration. This function uses {@link OAuthConfig} which is a configuration Type `@config`
   * with a hierarchy of override that starts at the application level `minOverride=APP` and goes up to the cluster
   * level `maxOverride=CLUSTER`.
   * 
   * @param accessTokenDuration
   *    Duration of the access token validity.
   */
  updateOAuthConfig: function(accessTokenDuration: string) : string js-server

  /**
   * The `fetchOAuthAppId` function fetches the OAuth application ID based on its name. The `OAuthApplication`
   * Type is an entity Type which means it represents a persistent object that can be stored and retrieved from a
   * database. The OAuthApplication contains a `name` field that represents the name of the OAuth application. It is
   * mandatory (!string denotes that the field is non-nullable).
   *
   * @param appName
   *    Name of the OAuth application.
   *
   * @returns Returns the application ID.
   */
  fetchOAuthAppId: function(appName: string) : string js-server
}

The supporting OauthPlayground.js provides the implementation of the functions in the OauthPlayground type.

The updateOAuthConfig function is responsible for updating the OAuth configuration on the C3 Agentic AI Platform. It takes an accessTokenDuration parameter, which represents the duration of validity for the access token. The function accesses the current OAuth configuration, specified by the OAuthConfig, and sets the accessTokenDuration value in the configuration. This configuration change affects the access token's validity duration within the C3 AI environment. The function returns a confirmation message indicating that the access token duration has been updated.

JavaScript
/**
 * Updates the OAuth configuration. This function uses {@link OAuthConfig} which is a configuration Type `@config`
 * with a hierarchy of override that starts at the application level `minOverride=APP` and goes up to the cluster
 * level `maxOverride=CLUSTER`.
 *
 * @param {number} accessTokenDuration - Duration of the access token validity.
 * @returns {string} - Confirmation message indicating that the access token duration has been updated.
 */
function updateOAuthConfig(accessTokenDuration) {
  // Get the current OAuth configuration.
  let config = OAuthConfig.inst().getConfig();
  // Update the access token duration in the configuration.
  config.setConfigValue("accessTokenDuration", accessTokenDuration);
  return "Access token set to " + accessTokenDuration;
}

The fetchOAuthAppId function is responsible for fetching the OAuth application ID based on the provided appName. This function interacts with the C3 Agentic AI Platform's database, utilizing the OAuthApplication Type, which represents a persistent object. The OAuthApplication Type has a name field that uniquely identifies the OAuth application. The function performs a database query to find the OAuth application with the given appName. If the application is found, it returns the corresponding application ID. However, if no matching application is found, it throws an error, indicating that the OAuth application must be registered.

JavaScript
/**
 * The `fetchOAuthAppId` function fetches the OAuth application ID based on its name. The OAuthApplication
 * Type is an entity Type which means it represents a persistent object that can be stored and retrieved from a
 * database. The OAuthApplication contains a `name` field that represents the name of the OAuth application. It is
 * mandatory (!string denotes that the field is non-nullable).
 *
 * @param {string} appName - Name of the OAuth application.
 * @returns {string} - Returns the application ID.
 * @throws {Error} - Throws an error if the OAuth application with the provided name is not found.
 */
function fetchOAuthAppId(appName) {
  // Fetch the OAuth application using the provided application name.
  const oAppId = OAuthApplication.fetch({
    filter: Filter.eq('name', appName)
  });
  // If no application is found, throw an error.
  if (oAppId.count === 0) {
    throw new Error(appName + " OAuthApplication not found. Please register the OAuth application first.");
  }
  // Return the ID of the fetched OAuth application.
  return oAppId.objs[0].id;
}

Troubleshoot utility functions

  • If you encounter issues with the updateOAuthConfig function, ensure that you have the necessary privileges and the correct configuration hierarchy within the C3 Agentic AI Platform.

  • When using fetchOAuthAppId, make sure that you have registered the OAuth application with the specified appName before attempting to fetch its ID.

Obtain an access token using the Client Credentials flow

The ClientCredentials.c3typ interacts with the C3 Agentic AI Platform's OAuth system. It provides functions for obtaining OAuth access tokens using the Client Credentials grant type.

Type
/**
 * The Client Credentials grant type is used by clients to obtain an access token outside of the context of a user.
 * This is typically used by clients to access resources about themselves rather than to access a user's resources.
 */
entity type ClientCredentials mixes OauthPlayground {

  /**
   * The `fetchToken` function sends the token request and fetches the access token. It uses the {@link UrlQuery} Type
   * that is designed to help with the construction and parsing of URL query strings. The {@link HttpRequest} Type
   * represents an HTTP request, which may be used to send requests to remote servers, modify requests, and convert
   * between formats.
   *
   * @param clientId
   *    The OAuth application ID.
   *
   * @param clientId
   *    The OAuth application client secret.   
   *
   * @param grantType
   *    The OAuth grant type.
   *
   * @returns Returns the access token.
   */
  fetchToken: function(clientId: string, clientSecret: string, grantType: string) : string js-server

  /**
   * The `generateOAuthToken` function is designed to handle OAuth token generation. It checks the validity of the
   * provided options, updates the OAuth configuration if necessary, fetches the relevant application ID based on the
   * application name, and then obtains an OAuth token for the app.
   * 
   * @param options
   *    Configuration options for token generation.
   *
   * @param options.appName
   *    Name of the application for which the token is to be generated. (Required)
   *
   * @param [options.accessTokenDuration]
   *    Optional duration for the validity of the access token.
   *
   * @param [options.grantType='client_credentials']
   *    OAuth grant type. 'client_credentials'.
   *
   * @returns Returns the generated access token.
   *
   * @throws Throws an error if the appName is not provided or if the accessTokenDuration is invalid.
   */
  generateOAuthToken: function(options: json): string js-server

}

The supporting ClientCredentials.js provides implementation details in JavaScript.

The fetchToken function is responsible for sending a token request to the OAuth server and retrieving the access token. It takes two parameters, appId (OAuth application ID) and grantType (OAuth grant type). The function constructs an HTTP request with the necessary parameters and sends it to the OAuth server. It then checks the response for the presence of the entity property, which contains the access token. If the token request is successful and the access token is found, it is returned. If any issues occur during the request or if the response does not contain the access token, an error is thrown.

JavaScript
/**
 * Sends the token request and fetches the access token.
 *
 * @param {string} grant_type - The OAuth grant type.
 * @param {string} client_id - The OAuth client ID.
 *  * @param {string} client_secret - The OAuth client secret.
 * @returns {string} - Returns the access token.
 * @throws {Error} - Throws an error if the token request fails or the response does not contain the access token.
*/
// Construct the function to fetch an OAuth token using client credentials.
function fetchToken(clientId, clientSecret, grantType) {
    // Create a URL query with the required parameters.
    const urlParams = {
      client_id: clientId,
      client_secret: clientSecret,
      grant_type: grantType
    };
    // Construct the HTTP request with method POST and the encoded URL parameters in the request body
    const request = HttpRequest.make({
      method: "POST"      
    }).withBodyString(UrlQuery.make().withStringParameters(urlParams).encode());
    // Send the token request to the OAuth server
    const response = OAuth.token(request);
  
    // Return the parsed access token
    const parsedResponse = JSON.parse(response.json());
    return parsedResponse.access_token;
  }

The generateOAuthToken function generates an OAuth access token. It accepts an options object with various configuration parameters:

  • appName (Required): The name of the application for which the token is generated.

  • clientSecret (Required): The clientSecret generated when registering the application.

  • accessTokenDuration (Optional): The duration of validity for the access token.

  • grantType (Optional,client_credentials): The OAuth grant type.

The function begins by validating that the required appName is provided. It also validates the accessTokenDuration if provided and checks that it is a valid number. If accessTokenDuration is provided, it updates the OAuth configuration accordingly using the updateOAuthConfig function from the OauthPlayground type.

Next, the function fetches the OAuth application ID based on the provided appName and the OAuth grant type. Finally, it uses the fetched application ID to obtain an access token by calling the fetchToken function. The generated access token is returned.

JavaScript
/**
 * @param {Object} options - Configuration options for token generation.
 * @param {string} options.appName - Name of the application for which the token is to be generated. (Required)
 * @param {number} [options.accessTokenDuration] - Optional duration for the validity of the access token.
 * @param {string} [options.grantType='client_credentials'] - OAuth grant type. Defaults to 'client_credentials'.
 * @returns {string} - Returns the generated access token.
 * @throws {Error} - Throws an error if required parameters are missing or if token generation fails.
 */
function generateOAuthToken(options) {
    // Check if options object and appName property is provided, if not throw an error.
    if (!options || !options.appName) {
      throw new Error('Missing required parameter: appName.');
    }
  
    // Destructure and set default values for the properties in the options object.
    const { appName, clientSecret, accessTokenDuration, grantType } = options;
    // Validate if the provided accessTokenDuration is a number, if not throw an error.
    if (accessTokenDuration !== undefined && typeof accessTokenDuration !== 'number') {
      throw new Error('Invalid accessTokenDuration value. It should be a number.');
    }
  
    // If accessTokenDuration is provided, update the OAuth configuration with the new duration.
    if (accessTokenDuration) {
      OauthPlayground.updateOAuthConfig(accessTokenDuration);
    }
  
    // Fetch the OAuth application ID using the provided appName.
    const appId = OauthPlayground.fetchOAuthAppId(appName);
    // Use the fetched application ID to get an access token and return it.
    return fetchToken(appId, clientSecret, grantType);
  }

Troubleshoot the client credentials flow

  • Ensure that the appName parameter is correctly provided when using the generateOAuthToken function. An incorrect or missing appName results in an error.

  • If you encounter issues with the accessTokenDuration parameter, make sure it is a valid number and corresponds to your desired access token validity duration.

Run the sample code

Here's an example of how to use the provided Types for obtaining an access token. Run the command in the C3 AI Console.

JavaScript
// Generate an OAuth token using Client Credentials grant type
const clientToken = ClientCredentials.generateOAuthToken({
  appName: "demoOAuthApp",
  clientSecret: "<clientSecret>",
  grantType: "client_credentials"
});

After running the sample code, the authorization server returns an access token to the clientToken variable. Here's an example of what the access token generated using the Client Credentials flow might look like:

Text
'eyJ0eXAiOiLKO345iLCJhbGciOiJSUzUxMiJ9.eyJhcHAiOiJzdGdna2V2OHRybjEtY21haGxrZTAwMy1vYXV0aHBsYXlncm91bmRwYWNrYWdlIiwib2F1dGhhcHBpZCI6InBlZWdrQ0hxVHVtU3BiMlBId295eHciLCJraW5kIjoiT0F1dGhBY2Nlc3NUb2tlbiIsImlzcyI6ImMzLmFpIiwiZ3JvdXBzIjpbIkMzLkFwcEFkbWluIl0sInNpZCI6MSwiYXVkIjoiYzMuYWkiLCJpZHAiOiIiLCJjM2dyb3VwcyI6WyJDMy5BcHBBZG1pbiJdLCJpZHBncm91cHMiOiJ7XCJPaWRjSWRwQ29uZmlnOjpzdGdna2V2OHRybjEuYzN0cmFpbmluZy5jbG91ZFwiOltcInN0Z2drZXY4dHJuMS5jM3RyYWluaW5nLmNsb3VkL0MzLlN0dWRpb1VzZXJcIl19Iiwic3NpZHgiOiIiLCJuYW1lIjoiZDQzZGVjZmU3ZDdhMjMzZDhlOTc1NWI2Y2EwMmRlNTA5MWEwNDEzY2M1NWQ1ZmM2OGEzMTRmZTg5N2QyYmU2YyIsImlkIjoiZDQzZGVjZmU3ZDdhMjMzZDhlOTc1NWI2Y2EwMmRlNTA5MWEwNDEzY2M1NWQ1ZmM2OGEzMTRmZTg5N2QyYmU2YyIsImV4cCI6MTY5NDk4MDc3Njc0NywiZW1haWwiOiJDaHJpcy5NYWhsa2VAYzMuYWkifQ.jyAsaiCpx6hMcVceISsTLJaMreskMqYQQKz4So-q-svN_PVbzT9q2qkns85VJHn2qzAFKw-wqhUyog6EndxMNwx168nPKv9NEf32tFWrySEqlo0ApCY4cXzv8TRjqUzMWEjJA7U8fO4kSIBUG9L5YEPJWdqwLTwS7BAp9iO7U4Ab1M0uB5KSH0LpxjgCsUNSxecn0l9YrL4IxDx0VdaTlX7dDZcM9zSTl11MFH3TByQkrdlIgVqztnN0s4OfB9ZgaKvwGI7h5xFRysQYakjZZvkniYJMkLiWb6qKlVt4TbEm3Ek8HZxehkrh8qs7Ue1e271GboXd659fAqHZA1lNBu'
Was this page helpful?