Configuring OIDC Client Credentials flow

This howto will show you how to configure OIDC Client Credentials flow. For other configuration options see here.

The purpose of Client Credentials flow is for non-interactive application to obtain a set of OIDC tokens for itself. Usually, the application then calls some other web-service where it authenticates itself with those OIDC tokens.

Steps to set up Authorization Code
  1. Prerequisites

  2. CAS configuration

  3. Testing

Prerequisites

The tutorial uses following values and examples. Change them according to your environment.

Table 1. Configuration values used throughout the tutorial
Item Value in examples

Appliance hostname on which the IdP is available

iam-appliance.tld

You must always use the full hostname. NetBIOS-style (or other) hostname fragments that do not specify the domain are not supported.

File with OIDC client registration

oidctest-201.json

cURL

You need only the curl or similar tool to test this flow.

CAS configuration

The IAM appliance comes with preconfigured defaults. The bare minimum you need to do is to register your OIDC application using CAS’s service registration file.

HTTP Endpoints and Issuer

HTTP endpoints and Issuer identity are auto-configured as follows. Hostname of the server is taken from your deployment settings, in our example it is iam-appliance.tld.

Parameter

Value

OIDC Issuer

https://iam-appliance.tld/cas/oidc

Token endpoint

https://iam-appliance.tld/cas/oidc/token

Userinfo endpoint

https://iam-appliance.tld/cas/oidc/profile

Registering OIDC service

Create service registration file for the OIDC oidctest-201.json and place it into /data/volumes-shared/cas-services/ directory.

Example service registration file.
{{
  "@class" : "org.apereo.cas.services.OidcRegisteredService",
  "clientId": "rlc-oidc-test",
  "clientSecret": "rlc-test",
  "serviceId" : "^https://this.url.does.not.matter",
  "name": "OIDC-RLC",
  "id": 201,
  "subjectType": "pairwise",
  "bypassApprovalPrompt": true,
  "scopes" : [ "java.util.HashSet", [ "openid"  ]],
  "supportedGrantTypes": [ "java.util.HashSet", [ "CLIENT_CREDENTIALS", "REFRESH_TOKEN" ] ],
  "supportedResponseTypes": [ "java.util.HashSet", [ "TOKEN" ] ],
  "attributeReleasePolicy" : {
    "@class" : "org.apereo.cas.services.ReturnMappedAttributeReleasePolicy",
    "allowedAttributes" : {
      "@class" : "java.util.TreeMap",
      "oidc_attribute_1" : "groovy { return ['somevalue'] }",
      "oidc_attribute_2" : "groovy { return ['someothervalue'] }",
      "oidc_attribute_X" : "groovy { return ['someotherothervalue'] }",
    }
  }
}
Table 2. Parameter definitions.
Parameter Value

clientId

OIDC client_id.

ASCII string. This value is assigned by CAS administrator, every OIDC client has its own. This is a login for your application.

clientSecret

OIDC client_secret.

This value is assigned by CAS administrator. Every client has its own. Secret must be safely stored on application server. This is a password for your application.

serviceId

OIDC redirect_uri.

This is mandatory field that has no effect when using Client Credentials flow.

name

Name of the service in CAS.

id

Unique id of application in CAS.

The id must match the number specified in the filename. In our case, the file is oidctest-201.json, so the id must be 201.

scopes

List of OIDC scopes the client is allowed to use.

Possible values for this scenario are: openid. Because we use scope-less claims.

supportedGrantTypes

What OIDC grants the client is allowed to use.

Possible values for this scenario are CLIENT_CREDENTIALS and (optional) REFRESH_TOKEN.

supportedResponseTypes

What protocol responses the client is allowed to get from CAS.

Possible values for this scenario are: TOKEN.

attributeReleasePolicy

Which user attributes are to be released by CAS.

We are using scope-less claim here so specifying the attribute release policy is mandatory.

Additional parameters

The service definition file may contain many more parameters as stated in the official CAS documentation.

Extending the configuration in such way may not be officially supported by the IAM appliance, though.

Testing

The Client Credentials flow works like this:

  1. Application uses client_id and client_secret to obtain access token from CAS.

  2. Application calls some other web-service and presents the access token.

  3. Web-service performs access token validation against CAS (backend-to-backend) and obtains the profile data.

  4. Web-service authorizes (or not) the application based on the profile data it got from CAS.

Testing the flow

  1. Issue yourself an access token…​

    curl -i 'https://iam-appliance.tld/cas/oidc/token?grant_type=client_credentials&client_id=rlc-oidc-test&client_secret=rlc-test&scope=openid
  2. …​and obtain the data.

    {
      "access_token":"AT-1-j3EPvr3jfHIVXEPnn4M8L-vMzg5L",
      "id_token":"eyJhbG... abbreviated ...8x8nAs6CaojdCw1YkFTv3qQu5VYCos_kn_f8uoHzCVkA",
      "token_type":"bearer",
      "expires_in":28800,"scope":"openid"
    }
  3. Use the access token to obtain user profile information. The response will contain all attributes you created in the service definition.

    curl -k -XGET --header "Authorization: Bearer AT-1-j3EPvr3jfHIVXEPnn4M8L-vMzg5L" https://iam.appliance.tld/cas/oidc/profile
  4. User profile is returned.

    {
      "sub":"rlc-oidc-test",
      "service":"rlc-oidc-test",
      "auth_time":1684333410,
      "id":"rlc-oidc-test",
      "client_id":"rlc-oidc-test",
      "attributes":{
        "oidc_attribute_1":"somevalue",
        "oidc_attribute_2":"someothervalue",
        "oidc_attribute_X":"someotherothervalue"
      }
    }