Decoding the ID Token

The ID Token is a security token that contains Claims (fields in token) about the user being authenticated. The Claims contains information such as the issuer, the expiration timestamp, subject identifier, nonce, and other fields depending on the scopes you requested.

We’re going to look at the format of an ID Token (JSON Web Token or JWT) and then examine what comprises the JWT: JOSE header, payload, and signature. At the end of the chapter, we’ll learn to decode and validate ID Tokens.

ID Token as a JSON Web Token (JWT)

The ID Token is represented as a JSON Web Token (JWT). The JWT is signed using a JSON Web Signature (JWS) and consists of three parts separated by ‘.’ (period).

An ID Token has the following syntax:

Base64(JOSE header).Base64(Payload).Base64(Signature)

JOSE Header

The JOSE header contains information regarding the signing algorithm. The JOSE header has the following fields:

  • alg - Identifies the cryptographic algorithm used to secure the JWS.
  • kid - The hint indicating which key was used to secure the JWS.

JOSE Header Example

In the example below, the value of the alg parameter "ES256". This indicates that the digital signature is encoded using the Elliptic Curve Digital Signature Algorithm (ECDSA) with the P-256 curve and the SHA-256 cryptographic hash function. See Creating a JWS with ECDSA P-256 SHA-256, ECDSA P-384 SHA-384, or ECDSA P-521 SHA-512 and Additional Algorithms for more information.

{
    "alg":"ES256",
    "kid":"87350ad9ce04550819b62079b193a42055a36b71"
}

ID Token Payload

The payload contains Claims about the authentication event. The following JSON fields are contained in the payload.

  • iss - (Issuer) The Issuer Identifier for the Issuer of the response. Clients must validate that the value is equal to https://api.login.yahoo.com.
  • sub - (Subject) The unique user identifier.
  • aud - (Audience) The value of the Client’s ID (client_id). Clients must verify that it is equal to their Client ID.
  • exp - (Expiration Time) The expiration for the ID Token. Clients must verify that this expiry time has not passed.
  • iat - (Issued At) The issue time for the ID Token.
  • nonce - The nonce passed as a parameter during authorization.
  • at_hash - (Access Token Hash Value) The Access Token hash (if issued with the flow), which can be used to mitigate cross-site request forgery (CSRF).

Additional Claims

Additional Claims may not be needed for SSO but can assist in creating a user account. Yahoo only returns additional Claims for the profile scope.

For the basic profile scope sdps-r, the following additional Claims are returned.

  • name - the full name of the user
  • given_name - the first name of the user
  • family_name - the last name of the user
  • locale - the preferred locale of the user

The extended profile scope sdpp-w, in addition to the Claims given above, also returns the following Claims:

  • email - the email ID of the user
  • email_verified - the Boolean flag letting Clients know if the given email address has been verified by Yahoo.

ID Token Payload Example

The example ID Token payload below, in addition to the Claims about the authentication event, also includes user information such as the user’s name and email address. These additional Claims were included because the read-write scope to the Profiles API (sdpp-w) was sent with the authentication request to Yahoo: scope=openid sdpp-w

{
   "sub": "MCX7TR7RTB5L3YRYR4FIAKX2IE",
   "aud": "dj0yJmk9NDdXZzBEcmJ6UjJxJmQ9WVdrOVlVWktjR0ZLTkdFbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD04OQ--",
   "email_verified": true,
   "iss": "https://api.login.yahoo.com",
   "name": "Jasmine Smith",
   "exp": 1440569876,
   "locale": "en-US",
   "given_name": "Jasmine",
   "nonce": "YihsFwGKgt3KJUh6tPs2",
   "iat": 1440566276,
   "family_name": "Smith",
   "email": "jasmine_smith@yahoo.com"
}

Signature

The last part of the ID Token is the digital signature, which is generated for the JOSE header and payload data (Base64(JOSE header).Base64(Payload)). Clients must validate the signature and return an error if the validation fails. To validate the signature, clients should fetch public keys from the keys endpoint. The endpoint is available from the jwks_uri field in the Yahoo Discovery document. We’ll learn to validate the signature in Validate the ID Token.

Decoding Example

We’re going to decode the following ID Token:

/#id_token=eyJhbGciOiJFUzI1NiIsImtpZCI6IjM0NjZkNTFmN2RkMGM3ODA1NjU2ODhjMTgzOTIxODE2YzQ1ODg5YWQifQ.eyJhdWQiOiJkajB5Sm1rOWJrMTVhM0ZYVjJ0NWNEbHRKbVE5V1Zkck9WbFZNWFJrYmtJMVRsUkJiV05IYnpsTlFTMHRKbk05WTI5dWMzVnRaWEp6WldOeVpYUW1lRDA0TUEtLSIsInN1YiI6IlVRSURXSk5XVk5RRDRHWFo1TkdNWlVTVFE0IiwiaXNzIjoiaHR0cHM6Ly9sb2dpbi55YWhvby5jb20iLCJleHAiOjE0NDQ2OTcwNDUsIm5vbmNlIjoiWWloc0Z3R0tndDNLSlVoNnRQczIiLCJpYXQiOjE0NDQ2OTM0NDV9.XiyNdHHHoYqarDZGkhln5sF_SQNNVvV67SZsFAk7yo8NreJjzVw7LmtkwpiUQe87-Km39PeIwf1W_PqEH9RqjA"
  1. First, extract the encoded JOSE header, the payload, and the signature by splitting the ID Token string on ”.”:

    jose_header = "eyJhbGciOiJFUzI1NiIsImtpZCI6IjM0NjZkNTFmN2RkMGM3ODA1NjU2ODhjMTgzOTIxODE2YzQ1ODg5YWQifQ"
    payload = "eyJhdWQiOiJkajB5Sm1rOWJrMTVhM0ZYVjJ0NWNEbHRKbVE5V1Zkck9WbFZNWFJrYmtJMVRsUkJiV05IYnpsTlFTMHRKbk05WTI5dWMzVnRaWEp6WldOeVpYUW1lRDA0TUEtLSIsInN1YiI6IlVRSURXSk5XVk5RRDRHWFo1TkdNWlVTVFE0IiwiaXNzIjoiaHR0cHM6Ly9sb2dpbi55YWhvby5jb20iLCJleHAiOjE0NDQ2OTcwNDUsIm5vbmNlIjoiWWloc0Z3R0tndDNLSlVoNnRQczIiLCJpYXQiOjE0NDQ2OTM0NDV9"
    signature = "XiyNdHHHoYqarDZGkhln5sF_SQNNVvV67SZsFAk7yo8NreJjzVw7LmtkwpiUQe87-Km39PeIwf1W_PqEH9RqjA"
    
  2. Use a Base64 library to decode the strings. You can use https://www.base64decode.org/ to help you decode the strings for this tutorial:

    jose_header = {
       "alg":"ES256",
       "kid":"3466d51f7dd0c780565688c183921816c45889ad"
    }
    
    payload = {
        "aud":"dj0yJmk9bk15a3FXV2t5cDltJmQ9WVdrOVlVMXRkbkI1TlRBbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD04MA--",
        "sub":"UQIDWJNWVNQD4GXZ5NGMZUSTQ4",
        "iss":"https://api.login.yahoo.com",
        "exp":1444697045,
        "nonce":"YihsFwGKgt3KJUh6tPs2",
        "iat":1444693445
    }
    
    signature = "XiyNdHHHoYqarDZGkhln5sF_SQNNVvV67SZsFAk7yo8NreJjzVw7LmtkwpiUQe87-Km39PeIwf1W_PqEH9RqjA"
    

    The alg Header Parameter is “ES256”, so you would validate the ECDSA P-256 SHA-256 digital signature contained in the JWS Signature.

  3. Congratulations, you have decoded your ID Token. The next step is to validate the ID Token.

Validate the ID Token

After decoding your ID Token, you will still need to validate it. Because the validation of an ID Token depends on an expiration time, instead of walking through an example, we’re going to instead provide you with validation steps.

1. Get the Public Keys

You’ll need the public keys from Yahoo to validate the signature. Make a GET request to the URL given by the jwks_uri parameter in the Yahoo Discovery document. In the returned JSON, you’ll see the array keys containing objects.

2. Find the Matching Public Keys

In the keys array, find the object with the kid and alg fields that have the same values as those in the JOSE header of your ID Token. Copy the object as we’ll be using its fields to validate the signature.

3. Determine the Cryptographic Algorithm

The alg field specifies the cryptographic library to use. For example, if the value for the alg field is “ES256”, you would validate the signature using the cryptographic library function for ECDSA P-256 SHA-256.

4. Validate the Signature

Use one of the available cryptographic libraries to validate the signature.

For example, if you were using the library Nimbus OAuth 2.0 SDK with OpenID Connect extensions (Java) to validate the signature, you would get the x and y values from the public keys (see step 2) and use something similar to the code below.

public boolean validateECDSASignatureWithNimbus(String x, String y) throws Throwable {
   JWSVerifier verifier = new ECDSAVerifier(new BigInteger(Base64.decodeBase64(x)), new BigInteger(Base64.decodeBase64(y)));
   return SignedJWT.parse(idToken).verify(verifier);
}

5. Check the Expiration

You’ll need confirm that the token has not expired by looking at the value of the exp field in your ID Token. Confirm that the current UNIX time has not exceeded the value of the exp field.

6. Confirm the Client ID

The aud field of your ID Token must match the Client ID of the application you created on YDN.

7. Verify the Issuer is Correct

Issuer is the Entity (in this case, Yahoo) who set the Claims. Thus, the value of the iss field in the ID token must be equal to https://api.login.yahoo.com.

8. Verify the Nonce is the Same

The nonce value returned in the ID Token should be the same as the value of the nonce parameter you transmitted to the authorization endpoint. This is to verify that you, and not someone else, initiated the request for the ID Token.

9. Use the Claims of the ID Token

After all the validations are successful, you can consume the Claims about the authenticated user from the ID Token.