Implicit Client Profile
The OpenID Connect 1.0 Implicit Client Profile uses the OAuth 2.0 "Implicit" grant type. The flow is almost identical to the OAuth 2.0 implicit flow with the exception of the "openid" scope and the tokens returned.
This section provides an example of using OpenID Connect Implicit Client Profile to retrieve an OpenID Connect id_token, validate the contents (steps 1 and 2 in the diagram below) and then query the UserInfo endpoint to retrieve profile information about the user (step 3).
This example assumes PingFederate 7.3 or higher is installed with the OAuth 2.0 Playground developer tool. The following configuration will be used:
PingFederate server base URL |
https://localhost:9031 |
OAuth 2.0 client_id |
m_oic_client |
OAuth 2.0 client_secret |
< none > |
Application callback URI |
https://localhost:9031/OAuthPlayground/case2A-callback.jsp |
For native mobile applications, the callback URI may be a non-http URI. This is configured in your application settings and will cause the mobile application to be launched to process the callback. |
Step 1: Authenticate the End-User and Receive Tokens
The initial user authentication request follows the OAuth2 Implicit Grant Type flow. To initiate the OpenID Connect process, the user will be redirected to the OAuth2 authorization endpoint. The request is made to the authorization endpoint with the following parameters:
client_id |
im_oic_client |
response_type |
token id_token |
redirect_uri |
https://localhost:9031/OAuthPlayground/case2A-callback.jsp |
scope |
openid profile |
nonce |
cba56666-4b12-456a-8407-3d3023fa1002 |
As the implicit flow transports the access token and ID token via the user agent (i.e. web browser), this flow requires additional security precautions to mitigate any token modification / substitution. |
As for the Basic Client Profile, the client can redirect the user in different ways depending on the client and the desired user experience. For example, a web application can just issue a HTTP 302 redirect to the browser and redirect the user to the authorization URL. A native mobile application may launch the mobile browser and open the authorization URL. NOTE: To mitigate replay attacks, a nonce value must be included to associate a client session with an id_token. The client must generate a random value associated with the current session and pass this along with the request. This nonce value will be returned with the id_token and must be verified to be the same as the value provided in the initial request.
https://localhost:9031/as/authorization.oauth2?client_id=im_oic_client &response_type=token%20id_token &redirect_uri=https://localhost:9031/OAuthPlayground/case2A-callback.jsp &scope=openid%20profile &nonce=cba56666-4b12-456a-8407-3d3023fa1002
Again, like the Basic Client Profile, the user will then be sent through the authentication process (i.e. prompted for their username/password at their IDP, authenticated via Kerberos or x509 certificate etc). Once the user authentication (and optional consent approval) is complete, the tokens will be returned as a fragment parameter to the redirect_uri specified in the authorization request.
GET https://localhost:9031/OAuthPlayground/Case2A-callback.jsp#token_type=Bearer &expires_in=7199 &id_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IjRvaXU4In0.eyJzdWIiOiJuZnlmZSIsImF1ZCI6Iml tX29pY19jbGllbnQiLCJqdGkiOiJUOU4xUklkRkVzUE45enU3ZWw2eng2IiwiaXNzIjoiaHR0cHM6XC9c L3Nzby5tZXljbG91ZC5uZXQ6OTAzMSIsImlhdCI6MTM5MzczNzA3MSwiZXhwIjoxMzkzNzM3MzcxLCJub 25jZSI6ImNiYTU2NjY2LTRiMTItNDU2YS04NDA3LTNkMzAyM2ZhMTAwMiIsImF0X2hhc2giOiJrdHFvZV Bhc2praVY5b2Z0X3o5NnJBIn0.g1Jc9DohWFfFG3ppWfvW16ib6YBaONC5VMs8J61i5j5QLieY-mBEeVi 1D3vr5IFWCfivY4hZcHtoJHgZk1qCumkAMDymsLGX-IGA7yFU8LOjUdR4IlCPlZxZ_vhqr_0gQ9pCFKDk iOv1LVv5x3YgAdhHhpZhxK6rWxojg2RddzvZ9Xi5u2V1UZ0jukwyG2d4PRzDn7WoRNDGwYOEt4qY7lv_N O2TY2eAklP-xYBWu0b9FBElapnstqbZgAXdndNs-Wqp4gyQG5D0owLzxPErR9MnpQfgNcai-PlWI_Urvo opKNbX0ai2zfkuQ-qh6Xn8zgkiaYDHzq4gzwRfwazaqA &access_token=b5bU8whkHeD6k9KQK7X6lMJrdVtV HTTP/1.1
An error condition from the authentication / authorization process will be returned to this callback URI with "error" and "error_description" parameters. |
The application now has multiple tokens to use for authentication and authorization decisions:
OAuth 2.0 access_token |
b5bU8whkHeD6k9KQK7X6lMJrdVtV |
OpenID Connect id_token |
eyJhbGciOiJSUzI1NiIsImtpZCI6IjRvaXU4In0.eyJzdWIiOi JuZnlmZSIsImF1ZCI6ImltX29pY19jbGllbnQiLCJqdGkiOiJU OU4xUklkRkVzUE45enU3ZWw2eng2IiwiaXNzIjoiaHR0cHM6XC 9cL3Nzby5tZXljbG91ZC5uZXQ6OTAzMSIsImlhdCI6MTM5Mzcz NzA3MSwiZXhwIjoxMzkzNzM3MzcxLCJub25jZSI6ImNiYTU2Nj Y2LTRiMTItNDU2YS04NDA3LTNkMzAyM2ZhMTAwMiIsImF0X2hh c2giOiJrdHFvZVBhc2praVY5b2Z0X3o5NnJBIn0.g1Jc9DohWF fFG3ppWfvW16ib6YBaONC5VMs8J61i5j5QLieY-mBEeVi1D3vr 5IFWCfivY4hZcHtoJHgZk1qCumkAMDymsLGX-IGA7yFU8LOjUd R4IlCPlZxZ_vhqr_0gQ9pCFKDkiOv1LVv5x3YgAdhHhpZhxK6r Wxojg2RddzvZ9Xi5u2V1UZ0jukwyG2d4PRzDn7WoRNDGwYOEt4 qY7lv_NO2TY2eAklP-xYBWu0b9FBElapnstqbZgAXdndNs-Wqp 4gyQG5D0owLzxPErR9MnpQfgNcai-PlWI_UrvoopKNbX0ai2zf kuQ-qh6Xn8zgkiaYDHzq4gzwRfwazaqA |
Because the implicit grant involves these tokens being transmitted via the user agent, these tokens cannot be kept confidential; therefore a refresh_token cannot be issued using this flow. |
Step 2: Validate the ID Token
The next step is to parse the id_token, and validate the contents. Note, that as the id_token was received via the user agent, rather than directly from the token endpoint, the verification of the digital signature is required to detect any tampering with the id_token. Firstly, decode both the header and payload components of the JWT:
Component | Value | Value Decoded |
---|---|---|
Header |
eyJhbGciOiJSUzI1NiIsImtpZCI6IjRvaXU4In0 |
|
Payload |
eyJzdWIiOiJuZnlmZSIsImF1ZCI6ImltX29pY19 jbGllbnQiLCJqdGkiOiJUOU4xUklkRkVzUE45en U3ZWw2eng2IiwiaXNzIjoiaHR0cHM6XC9cL3Nzb y5tZXljbG91ZC5uZXQ6OTAzMSIsImlhdCI6MTM5 MzczNzA3MSwiZXhwIjoxMzkzNzM3MzcxLCJub25 jZSI6ImNiYTU2NjY2LTRiMTItNDU2YS04NDA3LT NkMzAyM2ZhMTAwMiIsImF0X2hhc2giOiJrdHFvZ VBhc2praVY5b2Z0X3o5NnJBIn0 |
|
Now we follow the guidelines in the OpenID Connect specifications (Core specification section 3.1.3.7 also taking into consideration section 3.2.2.11) for ID Token Validation:
Step # | Test Summary | Result |
---|---|---|
1 |
Decrypt the token (if encrypted) |
Token not encrypted, skip test |
2 |
Verify the issuer claim (iss) matches the OP issuer value |
Valid |
3 |
Verify the audience claim (aud) contains the OAuth2 client_id |
Valid |
4 |
If the token contain multiple audiences, then verify that an Authorized Party claim (azp) is present |
Only one audience, skip test |
5 |
If the azp claim is present, verify it matches the OAuth2 client_id |
Not present, skip test |
6,7,8 |
Optionally verify the digital signature (required for implicit client profile) (see section 4.4) |
Verify signature as per "ID Token" section |
9 |
Verify the current time is prior to the expiry claim (exp) time value |
Valid |
10 |
Client specific: Verify the token was issued within an acceptable timeframe (iat) |
Valid |
11 |
If the nonce claim (nonce) is present, verify that it matches the nonce passed in the authentication request |
Nonce matches, Valid |
12 |
Client specific: Verify the Authn Context Reference claim (acr) value is appropriate |
No acr value present, skip test |
13 |
Client specific: If the authentication time claim (auth_time) present, verify it is within an acceptable range |
No auth_time present, skip test |
14 |
If the implicit client profile is used, verify that the access token hash claim (at_hash) matches the hash of the associated access_token |
Validate at_hash as per "ID_Token" section |
The results of the ID token validation are sufficient to trust the id_token and the user can be considered "authenticated".
Step 3: Retrieve the User Profile
We now have an authenticated user, the next step is to request the user profile attributes so that we can personalize their app experience and render the appropriate content to the user. This is achieved by requesting the contents of the UserInfo endpoint.
Accessing the UserInfo endpoint requires that we use the access token issued along with the authorization request. As the implicit flow transports the access token using the user agent, there is the threat of tokens being substituted during the authorization process. Before using the access token, the client should validate the at_hash value in the id_token to ensure the received access token was issued alongside the id_token.
To validate the at_hash value, see section 4.5. Once the at_hash is verified, the client can then use the access token to request the user profile:
GET https://localhost:9031/idp/userinfo.openid HTTP/1.1 Authorization: Bearer b5bU8whkHeD6k9KQK7X6lMJrdVtV
The response from the UserInfo endpoint will be a JSON structure with the requested OpenID Connect profile claims:
{
"sub":"nfyfe",
"family_name":"Fyfe",
"given_name":"Nathan",
"nickname":"Nat",
...[additional claims]...
}
Before we can be confident the response to the UserInfo reflects the authenticated user, we must also check that the subject ("sub" claim) returned from the UserInfo endpoint matches the authenticated user we received in the id_token. In this case, the "sub" claim in both the UserInfo response and the id_token match so we can use the values in the UserInfo response for our application needs.