Configure OAuth2 Client Credentials Grant

Get started with OAuth2 Client Credentials Grant by configuring a Client and then using it

Objective

The OAuth 2.0 Client Credentials Grant is one of the four standard OAuth 2.0 grant types, primarily used for machine-to-machine (M2M) communication. It allows a client (application) to obtain an access token on its behalf rather than on behalf of a user, which is a key distinction from other grant types like Authorization Code or Implicit Grant.

Purpose

The Client Credentials Grant is designed for situations where an application (the client) needs to access resources directly without user involvement. It is ideal when:

  • A service needs to communicate with another service securely.
  • The client is acting on its behalf and not on behalf of any user.

Common scenarios for Client Credentials Grant include:

  • Internal APIs where services need to communicate securely.
  • Automated server-to-server communication (e.g., cron jobs, background processes).
  • Applications that need to authenticate to obtain access to their own protected resources (e.g., management APIs).

How It Works

In this grant type, the client uses its client ID and client secret to authenticate directly with the authorization server and request an access token. The flow does not involve user authentication or authorization.

Here is the typical flow:

  1. Client Authentication: The client (application) sends a POST request to the authorization server’s token endpoint. It includes the client credentials (client ID and secret) in the request, along with the grant_type set to client_credentials.

    Example request:

    POST /token
    Host: authorization-server.com
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET
    
  2. Token Response: If the client credentials are valid, the authorization server responds with an access token. This token can be a Bearer Token, which allows the client to authenticate to the resource server.

    Example response:

    {
      "access_token": "ACCESS_TOKEN",
      "token_type": "Bearer",
      "expires_in": 3600
    }
    
  3. Access Resource: The client uses the access token to authenticate with the resource server and access protected resources. The token is included in the Authorization header as a Bearer token.

    Example request:

    GET /protected/resource
    Host: api.resource-server.com
    Authorization: Bearer ACCESS_TOKEN
    

Usage Considerations

  • Security: Since no user is involved, the security of the client credentials (ID and secret) is critical. These should be stored securely (e.g., in environment variables or secrets management systems) to avoid unauthorized access.
  • Scope: The access token may be limited by scope, which defines what actions or resources the client is allowed to access.
  • TTL: Tokens typically have a time-to-live (TTL) to limit the risk if the token is compromised. Clients need to handle token renewal when tokens expire.

Example Use Cases

  1. Microservices communication: A service accesses another service’s API (e.g., a payment service requesting data from an order service) without needing a user context.
  2. Infrastructure Management APIs: Automated tasks or cron jobs that need to interact with an infrastructure service (e.g., querying monitoring APIs).
  3. API Gateway Authentication: An API gateway authenticates itself with a downstream service to manage and route traffic securely.

Advantages

  • No user interaction is needed.
  • Simplifies server-to-server communication where a user context is not required.
  • Access can be scoped and time-limited via tokens.

The Client Credentials Grant is best suited for back-end services where user context is unnecessary, focusing on M2M authentication with high security for the client’s credentials.

OAuth2 Resource Owner Password Grant (ROPG) vs. Client Credentials Grant

1. Resource Owner Password Grant (ROPG)

Purpose: This grant allows a client to exchange a user’s username and password directly for an access token. It is mainly used when the client is highly trusted, like in first-party applications.

Use Cases:

When the client and resource owner (the user) are in the same entity.

Typically for legacy systems or trusted clients, like mobile or desktop applications, where other OAuth2 flows may be too cumbersome.

Security Concerns:

It involves sharing the user’s credentials with the client, so it has security risks and is often seen as insecure.

Deprecation: This grant is considered insecure for most modern applications and is discouraged from being used, with many OAuth2 providers deprecating it or restricting its usage. It’s deprecated in most cases.

2. Client Credentials Grant

Purpose: This grant is used when a client (e.g., a service or machine) needs to authenticate itself to an authorization server without user interaction.

Use Cases:

Service-to-service communications (API-to-API).

Machine-to-machine authentication.

Automated back-end systems that do not involve any end-user interaction.

Security: More secure than ROPG since it doesn’t involve handling user credentials and relies on a client’s credentials (client ID and secret). The client credentials are used to authenticate the client itself.

More Secure: The Client Credentials Grant is more secure since it avoids sharing user credentials with clients and is meant for machine-to-machine communication.

Access Management 2.0 Instructions for Client Credentials Grant

1. Creating a Client to Support Client Credentials Grant via Keycloak UI

  1. Log in to Access Management 2.0 Admin Console.

  2. Select the realm where you want to create the client.

  3. On the left-hand menu, click on Clients and then Create.

  4. Fill in the basic information for the client:

  • Client ID: Enter a unique client identifier.

  • Client Protocol: Select openid-connect.

  • Client Authentication: Set Client Authentication to ON.

  1. Under the Settings tab:
  • Access Type: Set it to Confidential (which enables client credentials flow).

  • Service Accounts Enabled: Set this option to ON.

  1. Save the client settings.

  2. Go to the Service Account Roles tab:

  • Assign the roles required for the client (usually roles like realm-management or specific resource roles that your client will need access to).
  1. Go to the Credentials tab to retrieve the Client Secret.

This secret will be used in the Client Credentials Grant to authenticate the client.

  1. The next step is to add claims that will be sent as part of the access token, or to be returned during the user info endpoint call. Go to the Client scopes tab. A dedicated scope will be automatically created for this client. Click on this scope.

  2. This scope will initially be empty. Here is where we need to add the user attributes. Click on Configure a new mapper.

  3. From this list of mappings, select the User Attribute mapper.

  4. In this example, we will see how to configure the “sub” attribute.
    Enter Name as sub.
    Enter User Attribute as sub.
    Enter Token Name Claim as sub.
    Select Claim JSON Type as String.
    Toggle ON Add to access token.
    Hit Save.

    We can see that the sub claim is now added to this client’s dedicated scope.

  5. Similarly, you can add other claims as per application requirements. To add another claim, click the Add Mapper dropdown and select the By configuration option.

  6. Repeat the same steps from 16-18 to map all the attributes (similar to sub attribute) as listed in the table below.

    User AttributeToken Claim NameClaim TypePresent in Access TokenPresent in ID TokenMultivalued
    subsubStringTRUEFALSEFALSE
    organizationorganizationStringTRUEFALSEFALSE
    userOrgsuserOrgsStringTRUEFALSETRUE
    bulkOrganizationAccessbulkOrganizationAccessbooleanTRUEFALSEFALSE
    userBusinessUnitsuserBusinessUnitsStringTRUEFALSETRUE
    excludedUserBusinessUnitsexcludedUserBusinessUnitsStringTRUEFALSETRUE
    bulkBusinessUnitAccessbulkBusinessUnitAccessbooleanTRUEFALSEFALSE
    userDefaultsuserDefaultsJSONTRUEFALSETRUE
    userLocationsuserLocationsJSONTRUEFALSETRUE
    largeStoreAccesslargeStoreAccessbooleanTRUEFALSEFALSE
    localelocaleStringTRUETRUEFALSE
    edgeedgeStringTRUEFALSEFALSE
    tenantIdtenantIdStringTRUEFALSEFALSE
    userTimeZoneuserTimeZoneStringTRUEFALSEFALSE
    authoritiesauthoritiesStringTRUEFALSETRUE
    reporting_rolesreporting_rolesStringTRUEFALSETRUE
    user_nameuser_nameStringTRUEFALSEFALSE
  7. Navigate to the Scope tab of this dedicated scope and toggle OFF the Full scope allowed option.

Creating the Client with Client Credentials using Manhattan REST API

Use the following REST API to create an OAuth client in Keycloak to be used with client credential grant requests coming from another system (robot user). Replace “” and “” string in the example payload below with a specific value. “access_token_validity” is a number field indicating token expiry in seconds. I.e. a value of 1800 represents 30 minutes.

  POST /clients
  Content-Type: application/json
  Authorization: Bearer {admin-access-token}
  {
      "client_id": "<client-id>",
      "client_secret": "<client-secret>",
      "scope": ["openid"],
      "authorized_grant_types": ["service_account"],
      "access_token_validity": 1800
  }

When a client is created with service account access, an associated user account named “service-account-” is also created. The attributes configured for this user determine the claim values of the access token fetched using a client credential grant. For access tokens to be used with MA Product REST APIs successfully, a specific set of attributes needs to be configured for this service account user. Following is the list of attributes with example values.

Adding Custom Attributes/Claims to the Service Account User

1. Through Access Management 2.0 Admin Console:

  • Go to Users in the Access Management 2.0 Admin UI.

  • Search for the service account user. The username will be in the format service-account-{client-id}. Please replace the {client-id| with your client_id

  • Once you find the user, click on it.

  • Go to the Attributes tab and add the custom attributes you need.

2. Through the Access Management 2.0 Admin REST API:

Retrieve the Service Account User ID:

    GET /{realm}/clients/{client-id}/service-account-user
    Authorization: Bearer {admin-access-token}

Add Attributes:

    PUT /{realm}/users/{service-account-user-id}
    Authorization: Bearer {admin-access-token}
    Content-Type: application/json
    {
      "attributes": {
        "custom-attribute-key": ["custom-value"]
      }
    }

Adding Custom Claims to Tokens:

  1. Create a Protocol Mapper for Custom Claims:
  • In the client settings, go to the Mappers tab.

  • Click on Create.

  • Choose a built-in Protocol Mapper like User Attribute.

  • Set the token claim name and specify the user attribute to map to it.

With this setup, you can ensure the Client Credentials Grant is implemented securely with proper control over the service account user and its attributes/claims.

To update the client secret for a client in Keycloak using the REST API, you can follow these steps:

Generate a New Secret via REST API

You can regenerate the client secret using the following API call:

Request:

    POST /{realm}/clients/{client-id}/client-secret
    Authorization: Bearer {admin-access-token}
  • Replace {realm} with your Keycloak realm name.

  • Replace {client-id} with the ID of the client whose secret you want to regenerate.

  • {admin-access-token} is the token you get when logging in as an admin user (you can obtain this token via Keycloak Admin API login).

Response:

This request will generate a new client secret and return it in the response body. The response will look like this:

  {
      "type": "client-secret",
      "value": "new-generated-client-secret"
  }

The “value” will contain the newly generated client secret.

Update the Client Secret Manually via REST API

If you want to set a specific client secret manually (instead of generating a new one), you can update the secret as follows:

Request:

    PUT /{realm}/clients/{client-id}
    Authorization: Bearer {admin-access-token}
    Content-Type: application/json
    {
        "clientId": "your-client-id",
        "secret": "your-new-client-secret",
        "clientAuthenticatorType": "client-secret"
    }
  • In this case, replace “your-new-client-secret” with the secret you want to set.

  • Replace {realm} with your Keycloak realm name and {client-id} with the client ID.

This will update the client’s secret to the provided value.