Configuring OIDC Resource Owner Password flow

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

In Password flow, the 3rd-party application can obtain OIDC tokens on behalf of user by sending user’s credentials to the authorization server. The 3rd-party application presents its own login form for user to enter login and password into.

Password flow was dropped from newer versions of OIDC specification because it reveals user’s password to the 3rd-party application - that is a security issue. However, if you or your organization also develop (or operate) the application in question then there is no such security risk.

There are still risks related to user entering password into other applications other than the Access Manager, though.

Steps to set up Password Flow
  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

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,
  "tokenEndpointAuthenticationMethod": client_secret_post,    // if left out, it defaults to Basic authentication
  "scopes" : [ "java.util.HashSet", [ "openid"  ]],
  "supportedGrantTypes": [ "java.util.HashSet", [ "PASSWORD", "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.

clientSecret

OIDC client_secret.

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

serviceId

OIDC redirect_uri.

This is mandatory field that has no effect when using Password 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.

tokenEndpointAuthenticationMethod

client_secret_post, client_secret_basic

Where the token endpoint should expect values of client_id and client_secret to authenticate the token request.

supportedGrantTypes

What OIDC grants the client is allowed to use.

Possible values for this scenario are PASSWORD 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.

User authorization conditions specified in CAS service’s configuration do not take effect when using Password Flow.

Testing

The Password flow works like this:

  1. Application gathers user’s username and password using its own login form.

  2. Application uses client_id, client_secret, username, password and scope to obtain access token from CAS.

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

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

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

Testing the flow

  1. Issue an access token for the user foo who has password bar…​

    curl -i -XPOST --data "client_id=oidc-test&client_secret=rlc-test&grant_type=password&scope=openid&username=foo&password=bar" "https://iam-appliance.tld/cas/oidc/token"
  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":"foo",
      "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"
      }
    }