OpenID Connect ID token validation.

Validating an OpenID Connect ID Token

On this page

About ID Token Validation

This article describes how to validate an OpenID Connect ID Token. What each part of the token means and how to use them after user authentication.

The ID Token is a JWT with specified contents, defined by the OpenID Foundation in the OpenID Connect Core Specification. The ID token provides proof of the authentication event to OpenID Connect clients. It contains information about how and when the user authenticated. Clients can also use ID Tokens to receive additional attributes about the user identity.

The ID Token JWT

The ID Token is an encoded and signed JSON Web Token (JWT). The JWT format is specified in RFC7519 . A JSON Web Token is a compact and URL-safe way of passing a JSON message between two parties.

The ID token contains claims issued by the OpenID Connect Provider (the Curity Identity Server). The ID Token is always a JWT. It cannot be issued as an opaque reference token.

The ID token consists of three main parts:

  • header - Metadata about the token and its cryptographic algorithm
  • payload - Claims about the issuer, the user and user authorization
  • signature - For verification of the integrity of the token

The parts are separated with a . period in the encoded token:

Example:

text
1
eyJraWQiOiItMzgwNzQ4MTIiLCJ4NXQiOiJNUi1wR1RhODY2UmRaTGpONlZ3cmZheTkwN2ciLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiQ2djcDVvaWtzdDM4M2NBYl9KNU1WUSIsImRlbGVnYXRpb25faWQiOiI4MDkxZDEzMi02OGRkLTQ2YzMtYWRiZC0xYzgzNjQzYzRhNTciLCJhY3IiOiJ1cm46c2U6Y3VyaXR5OmF1dGhlbnRpY2F0aW9uOmh0bWwtZm9ybTpodG1sU3FsIiwic19oYXNoIjoiYXFpRFYxQ3k2U0NzZmEyQXlOcjVfUSIsImF6cCI6ImNsaWVudC1vbmUiLCJhdXRoX3RpbWUiOjE1NTA4MzMxNDgsIm5vbmNlIjoiMTU1MDgzMzExODA5Ni1IVm0iLCJleHAiOjE1NTA4MzY4MDcsIm5iZiI6MTU1MDgzMzIwNywianRpIjoiZTc1ZmQ0ZTctNjVjNC00ZmVlLWJjYjYtZGUxZjI5OTYwMTViIiwiaXNzIjoiaHR0cHM6Ly9leGFtcGxlLmN1cml0eS5pbyIsImF1ZCI6ImNsaWVudC1vbmUiLCJzdWIiOiJqb2huZG9lIiwiaWF0IjoxNTUwODMzMjA3LCJwdXJwb3NlIjoiaWQifQ.kKq2h2x20K-eXtoAeTFsjOIFzmfTjR8zP5F48qTQAkAK9qLKJCQkJ9UkAmHUw9BVgfb2zxLiRG6e5ACTpmxR_Mqv4mFeGyBR1faLJTXwdmiuJqqBcCKWS48KmhE-7XkxoF9nuiU_aaQArVn-Cx3qI2pQ945qUcXa47J2vn0xxGpm82VLQNfCsttT4M7HU-SjvTHOqS439bKl4gIcg-MIxmog08J5GdQpmyt7p2-cGvwd4iQVcd5t6sL0hcw5Q36sLSRnms4e8F9xWLZS2cD6ppdv4h8nr9whQB5NtIbw10f8rgy6o6vODu91JoxrAodTyu6QlVtN6uugicAR4OWs5w

OAuth Tools

You can use Curity's OAuth Tools to decode and analyze JWTs to try them out.

Decode the ID Token

To decode the token, you need to do a base64url decode of each part. The decoded parts will be represented as JSON content data. Split the token on the . period.

Header

The header contains metadata, such as and the hash algorithm used for the token contents, and (somewhat redundantly for our purposes) the type of token.

Example:

json
12345
{
"kid": "-38074812",
"x5t": "MR-pGTa866RdZLjN6Vwrfay907g",
"alg": "RS256"
}

The header should be used to figure out what key to use when validating the token. There are a few options but the most common ones are:

kid : The key id. The key is found on the Json Web Key Set (JWKS) endpoint of the issuer.

x5t or x5t#256 : The fingerprint of the certificate to use hashed with SHA1 or SHA256.

alg : The algorithm used when signing the token. This should be a strong enough algorithm. Do not rely on this solely. Libraries should block algorithms such as none to prevent attacks.

x5t is commonly used when the certificate is pre-distributed to the clients, and kid when JWKS is used.

For more information, see the Registered Header Parameter Names section of RFC7515 - JSON Web Signature.

Payload

The Payload contains the claims for use by the client. When decoding the first thing to look for is the iss issuer field. It shows who issued the token and must be an HTTPS url. This is important for the following reasons:

  • Only trust tokens from known issuers
  • Use the issuer to find the JWKS endpoint via the OpenID Connect Metadata

Example:

json
1234567891011121314151617
{
"at_hash": "Cgcp5oikst383cAb_J5MVQ",
"delegation_id": "8091d132-68dd-46c3-adbd-1c83643c4a57",
"acr": "urn:se:curity:authentication:html-form:htmlSql",
"s_hash": "aqiDV1Cy6SCsfa2AyNr5_Q",
"azp": "client-one",
"auth_time": 1550833148,
"nonce": "1550833118096-HVm",
"exp": 1550836807,
"nbf": 1550833207,
"jti": "e75fd4e7-65c4-4fee-bcb6-de1f2996015b",
"iss": "https://example.curity.io",
"aud": "client-one",
"sub": "johndoe",
"iat": 1550833207,
"purpose": "id"
}

Signature

The last part of the ID Token is the signature, which you use to to verify that the token was issued by the trusted issuer and not tampered with in route.

text
1
kKq2h2x20K-eXtoAeTFsjOIFzmfTjR8zP5F48qTQAkAK9qLKJCQkJ9UkAmHUw9BVgfb2zxLiRG6e5ACTpmxR_Mqv4mFeGyBR1faLJTXwdmiuJqqBcCKWS48KmhE-7XkxoF9nuiU_aaQArVn-Cx3qI2pQ945qUcXa47J2vn0xxGpm82VLQNfCsttT4M7HU-SjvTHOqS439bKl4gIcg-MIxmog08J5GdQpmyt7p2-cGvwd4iQVcd5t6sL0hcw5Q36sLSRnms4e8F9xWLZS2cD6ppdv4h8nr9whQB5NtIbw10f8rgy6o6vODu91JoxrAodTyu6QlVtN6uugicAR4OWs5w

Validate the ID Token

After initial decoding the token can be validated.

Signature

The signature is generated using the hashing algorithm from the token header.

To verify the signature, you must:

  • Check the signing algorithm
  • Verify signature with a public key

Check Algorithm

The alg value for the signature should be of the expected type. (Whitelist the types your organization allows)

Verify signature

To verify the signature you should:

  • Retrieve the public key by using the x5t or kid parameter.
  • Break off the signature from the message leaving the header.payload encoded
  • Convert the header+payload segment to an ASCII array
  • Base64Url decode the signature
  • Use the decoded signature to validate the header+payload ASCII byte array

Verifying Standard Claims

Once the token has been received and decoded, you can validate the claims it contains, to make sure that they match the expected values:

ClaimDescriptionComment
acrAuthentication method usedShould match the acr_values request parameter (if it was sent in the request).
issIssuerIdentifier for the creator of the token. Must be a plain https:// URL.
subSubjectIdentifier for the authenticated user.
audAudienceExpected recipient(s). Must contain some identifier for client, for example the Client ID or domain.
iatIssued AtWhen the ID Token was issued.
auth_timeAuthentication TimeWhen the user last was logged in without SSO.
jtiToken identifierA unique identifier for this token. Can be used to prevent replays
nonceNonceIf the client passed in a nonce when requesting the token it must be present here

ID Tokens vs Access Tokens

ID tokens and access tokens have different audiences. The ID token provides proof of the authentication event, to inform the client how and when the user authenticated. The ID token can also provide other identity values to the client. ID tokens are private to the client and should never be sent to APIs.

Access tokens are also received by clients, who treat them as opaque strings and send them as message credentials when calling APIs. Access tokens are received by APIs in a JWT format. They contain secure values used for authorization, and are validated in a similar way to ID tokens. Access tokens include scopes and have short lifetimes, unlike ID tokens.

For more information about JWTs, and how to overcome potential risks when working with them, see the JWT Security Best Practices article.

Photo of Jacob Ideskog

Jacob Ideskog

Identity Specialist and CTO at Curity

Join our Newsletter

Get the latest on identity management, API Security and authentication straight to your inbox.

Start Free Trial

Try the Curity Identity Server for Free. Get up and running in 10 minutes.

Start Free Trial