Rate this page

A first look

To give us some context for the articles that follow, let’s follow a simple client application as it uses the Data Governance Broker to authenticate a user and retrieve some attributes belonging to the user.

The scenario

In this example, we have a server-side web application that uses sessions to track login state for its users, but it doesn’t implement any complex authentication logic of its own, nor does it store user profile data in its own data store. Authentication and user data responsibilities are delegated to the Data Governance Broker. This keeps the application simple. Other applications can avail themselves of the Data Governance Broker’s services, too, which is a boon for users, who don’t have to maintain passwords and profiles for each application or learn to trust multiple login interfaces.

The application is going to use OpenID Connect to authenticate a user through the Data Governance Broker. When that succeeds, the application will make a SCIM request to the Broker to obtain some profile data for the user.

Step 1: Authentication request

First, when the user loads the application, the application creates a session and stores a unique session value, called a nonce.

Sample app home page

Then, the application creates an OpenID Connect authentication request. This is a redirect to the Data Governance Broker’s authorization endpoint, and it looks like this:

https://example.com/oauth/authorize?client_id=groovy-sign-in-sample
&response_type=code
&scope=openid+name+email
&redirect_uri=https://example.com/callback
&state=eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJncm9vdnktc2lnbi1pbi1zYW1wbGUiLCJyZXR1cm5fdXJpIjoiXC9wcm90ZWN0ZWRcL2RlZmF1bHQiLCJleHAiOjE0NzMzMTM3NzAsImlhdCI6MTQ3MzMxMjg3MCwicmZwIjoiZXJnMm42ZnJqb2xocHU0MjEycmJiaWduNjMifQ.NTTxOXGYKHDBh4OOp2LwSw_FswhxwX3sELDyQJ8oNjU
&nonce=9gpn6cl8vaskvrp0uf4p924jem

Let’s briefly go over the request parameters. We’ll be discussing them again throughout this guide.

  • client_id: A unique identifier for the application.
  • response_type: Designates the type of OpenID Connect flow to be used. In this case, it’s the authorization code grant type, which is used by server-side web applications.
  • scope: These declare the extent of access to user data that the application seeks.
  • redirect_uri: This is an endpoint belonging to the application. The Data Governance Broker will redirect the user’s browser to it when the authentication process is complete.
  • state: This is an encoded value that will be passed back to the application by the Data Governance Broker. It contains information that the application will use to pick up from where it left off.
  • nonce: This is the value that the application generated earlier when it established its session. This will also be passed back to the application by the Data Governance Broker.

Step 2: Authentication

Upon receipt of the authentication request, the Data Governance Broker will redirect the user to the login page for authentication. At this point, the application is temporarily out of the picture, and the user is interacting directly with the Data Governance Broker.

The authentication process is extremely customizable, but typically, the user will be presented with a username/password prompt.

Data Governance Broker login page

Once the user logs in, the Data Governance Broker may or may not prompt the user for another credential, depending on its policies. The other credential could be a verification code sent to an SMS number, a time-based one-time password managed using a smartphone app such as Google Authenticator, or something else entirely.

Step 3: Authorization

Once authentication is complete, the user will be prompted to provide consent to the application’s request. The contents of the consent prompt will bear a direct relation to the scopes that the application listed in its authentication request.

Data Governance Broker consent page

Step 4: Authentication response handling

Once the user clicks the Accept button, then the user is authenticated to the Data Governance Broker, and the request is authorized. The Data Governance Broker will generate a short-lived, unique code called an authorization code. It will append the authorization code and the state value that the application provided to the application’s redirect URI and then redirect the user’s browser to this URI.

http://example.com/callback?code=ATE4FuRVh9UF7j5hBqcBvinHJMTOAAAAAAAAAABX1jzWNVyG4cdigxLNfMxQl0SDlEOFCSFqT_AmJgZTThIIKqRvknk9ysHJjO8PtCzzl3MC5Ke_6AhctuV4RBlMufo9P9MbVceE0ixJrxg1QQ
&state=eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJncm9vdnktc2lnbi1pbi1zYW1wbGUiLCJyZXR1cm5fdXJpIjoiXC9wcm90ZWN0ZWRcL2RlZmF1bHQiLCJleHAiOjE0NzMzMTM3NzAsImlhdCI6MTQ3MzMxMjg3MCwicmZwIjoiZXJnMm42ZnJqb2xocHU0MjEycmJiaWduNjMifQ.NTTxOXGYKHDBh4OOp2LwSw_FswhxwX3sELDyQJ8oNjU

The application will first verify that the state value that it just received is the same value that it sent. Then it will take the authorization code and exchange it for an access token.

It will do this by sending the authorization code to the Data Governance Broker’s token endpoint.

POST /oauth/token HTTP/1.1
Authorization: Basic Z3Jvb3Z5LXNpZ24taW4tc2FtcGxlOmJacDZpbTlzTDI5YTQ5bXJZdkk2Q0NwR3Q5SUJvdFl2
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: example.com

grant_type=authorization_code&code=ATE4FuRVh9UF7j5hBqcBvinHJMTOAAAAAAAAAABX1jzWNVyG4cdigxLNfMxQl0SDlEOFCSFqT_AmJgZTThIIKqRvknk9ysHJjO8PtCzzl3MC5Ke_6AhctuV4RBlMufo9P9MbVceE0ixJrxg1QQ&redirect_uri=http://example.com/callback

The Data Governance Broker will respond with an access token and an ID token.

HTTP/1.1 200 OK
Cache-Control: no-store
Content-Length: 1504
Content-Type: application/json
Date: Thu, 08 Sep 2016 06:32:26 GMT
Pragma: no-cache

{
  "scope": "openid name email",
  "access_token": "eyJraWQiOiJBY2Nlc3MgVG9rZW4gU2lnbmluZyBLZXkgUGFpciIsImFsZyI6IlJTNTEyIn0.eyJzdWIiOiJVc2Vyc1wvZTJjZTg2ZmUtZjVlYi00ZWJlLTg0ODYtMGQwNDYzNjA0MDc4Iiwic2NvcGUiOiJvcGVuaWQgbmFtZSBlbWFpbCIsImV4cCI6MTQ3MzM5OTI3OCwiaWF0IjoxNDczMzEyODc4LCJjbGllbnRfaWQiOiJncm9vdnktc2lnbi1pbi1zYW1wbGUiLCJqdGkiOiJhLmVsUExCQSJ9.IcGE-WFHmfyPkSvwSgJZ51zeNmbZ_wLdq7TJDMnEOL4J9XfjFSdZ_-YMcQRC8m5bBB1-wpj_aJewKia9CoT_K38utAhwbR_tMSM1vbhMYQW4A3fFjcDjjrDYr11FvQw7Zb3wbUkIDMqkPSKxGMTOo9_1Y82w7ak0YsvTqufKr8-96EbD4Xvb7ngSiT8KP0_Z0p2SFF9NleibmdfQF0gcJeFYPRlZ0QoIXpZ2B4Y8p9oO9AX2OSIt3s5tk3FjpnaGlicyw9L-1DZPKY3T6qVlHALM_XaRfNv86PLH_q9s2CwnltcfDRRx8XwLQJkzSe1q_rP05RgauYbiBVPSXGfLMg",
  "token_type": "Bearer",
  "expires_in": 86400,
  "id_token": "eyJraWQiOiJzYW1wbGUtaWR0b2tlbi1rZXkiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoic3BhTmZPaFBFcFFHOHdtLVBTMmVmQSIsImFjciI6IkRlZmF1bHQiLCJzdWIiOiJVc2Vyc1wvZTJjZTg2ZmUtZjVlYi00ZWJlLTg0ODYtMGQwNDYzNjA0MDc4IiwiYXVkIjoiZ3Jvb3Z5LXNpZ24taW4tc2FtcGxlIiwiYW1yIjpbInB3ZCJdLCJhdXRoX3RpbWUiOjE0NzMzMTI4NzYsImlzcyI6Imh0dHBzOlwvXC9leGFtcGxlLmNvbSIsImV4cCI6MTQ3MzMxMzc3OCwiaWF0IjoxNDczMzEyODc4LCJub25jZSI6IjlncG42Y2w4dmFza3ZycDB1ZjRwOTI0amVtIn0.d3A7_1OgQcrBOEe39gM7wBrihGr6D1gR0B3rq0h4-8UmXfNqvXuiGAEozOfRli0UKdWLoLhS_PhX4dH8xb15tRYyQuSkIcm7f-ZZa5UqqmZouna7pR9apPDnypfFaLG36kCb803QdBZKkuoB-OothiF9VUKtvRCHL3M5Jk8irusUL9RV3zy8cD8LwihrAn9JRkNoyLbhCww-q8JdjlXvxmyAqoKysfF3t6WuG59ArSmEfjrZlzHTfx794jowUWDTG99YmzUAu-vrKHMv5lsDhrzK3UKJ8pZVf0WyuQ_jorBb5zk1XG566wKuZv2U8qBHTjDPJmJLYn5weNSs8DZBTQ"
}

The ID token is essentially a set of assertions from the Data Governance Broker about the user’s authentication state. The application will validate the ID token — including checking the nonce against the session — and then mark its session as authenticated.

The access token is used in the next step.

Step 5: Profile retrieval

The user is now authenticated to the application. If this is all that the application needs, then it’s done. In our case, the application also needs to retrieve some user profile data from the Data Governance Broker.

To retrieve data, the application will use the access token. It acts as a credential to the Data Governance Broker’s SCIM service, representing the user’s authorization to access protected data.

The application makes a GET request to the Me endpoint:

GET /scim/v2/Me HTTP/1.1
Accept: application/scim+json
Authorization: Bearer eyJraWQiOiJBY2Nlc3MgVG9rZW4gU2lnbmluZyBLZXkgUGFpciIsImFsZyI6IlJTNTEyIn0.eyJzdWIiOiJVc2Vyc1wvZTJjZTg2ZmUtZjVlYi00ZWJlLTg0ODYtMGQwNDYzNjA0MDc4Iiwic2NvcGUiOiJvcGVuaWQgbmFtZSBlbWFpbCIsImV4cCI6MTQ3MzM5OTI3OCwiaWF0IjoxNDczMzEyODc4LCJjbGllbnRfaWQiOiJncm9vdnktc2lnbi1pbi1zYW1wbGUiLCJqdGkiOiJhLmVsUExCQSJ9.IcGE-WFHmfyPkSvwSgJZ51zeNmbZ_wLdq7TJDMnEOL4J9XfjFSdZ_-YMcQRC8m5bBB1-wpj_aJewKia9CoT_K38utAhwbR_tMSM1vbhMYQW4A3fFjcDjjrDYr11FvQw7Zb3wbUkIDMqkPSKxGMTOo9_1Y82w7ak0YsvTqufKr8-96EbD4Xvb7ngSiT8KP0_Z0p2SFF9NleibmdfQF0gcJeFYPRlZ0QoIXpZ2B4Y8p9oO9AX2OSIt3s5tk3FjpnaGlicyw9L-1DZPKY3T6qVlHALM_XaRfNv86PLH_q9s2CwnltcfDRRx8XwLQJkzSe1q_rP05RgauYbiBVPSXGfLMg
Content-Type: application/scim+json
Host: example.com

And receives the user’s profile. This may not be the user’s entire profile — the attributes in this response are constrained by the access token’s scopes.

HTTP/1.1 200 OK
Content-Length: 602
Content-Type: application/scim+json
Date: Thu, 08 Sep 2016 06:43:13 GMT

{
    "emails": [
        {
            "primary": true,
            "type": "work",
            "value": "pat.conley@runciter.com"
        }
    ],
    "id": "e2ce86fe-f5eb-4ebe-8486-0d0463604078",
    "meta": {
        "created": "2016-09-07T17:47:51.588Z",
        "lastModified": "2016-09-08T05:34:38.712Z",
        "location": "https://example.com/scim/v2/Users/e2ce86fe-f5eb-4ebe-8486-0d0463604078",
        "resourceType": "Users"
    },
    "name": {
        "familyName": "Conley",
        "formatted": "Pat Conley",
        "givenName": "Pat"
    },
    "schemas": [
        "urn:pingidentity:schemas:sample:profile:1.0",
        "urn:pingidentity:schemas:User:1.0"
    ],
    "userName": "user.5"
}

Now that the user is authenticated and the application has the user’s profile data, the application is done and may render its view to the user.

Sample app protected resource page