Token Endpoint

The next step is to claim an access_token used to retrieve user claims by exchanging the authorization code received in the previous step at the Interac Hub's token_endpoint.

POST /oauth2/token HTTP/1.1
Host: hub_server.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=val1&code=val2&client_assertion_type=val3&client_assertion=val4&client_id=val5&redirect_uri=val6&code_verifier=val7

The request body has several parameters:

REQUIREMENTPARAMETEREXAMPLE VALUEDESCRIPTION
Requiredgrant_typeauthorization_codeAlways set to authorization_code to indicate OAuth 2.0 authorization code grant flow.
Requiredcode5GT81abUDETEOpVegW....hQHRcR8QThe authorization code returned in the authorization grant response.

The provisioned authorization code can only be redeemed once.
Requiredclient_assertion_typeurn:ietf:params:oauth:client-assertion-type:jwt-bearerThis is always set to urn:ietf:params:oauth:client-assertion-type:jwt-bearer per RFC 7523 JSON Web Token Profile.
Requiredclient_assertioneyJhbGciOiJSUzI1NiI...\_9xOx-1_sYxASigned Client Assertion Object
A client assertion object in a signed JWT (JWS) compact-serialized format. Refer to RFC 7519 JSON Web Tokens and RFC 7515 JWS compact serialization.

This JWS must be signed by the RP using the private portion of an RSA keypair. The public portion is the one published to the RP's JWKS endpoint and registered with the Hub during onboarding (via the RP's JWKS URL).

A number of parameters need to be included in this JWS and are detailed in the subsequent table.
Requiredclient_idhub-int-teamThe same client ID used in the authorization grant request.
Requiredredirect_urihttp://localhost:5000/loginResponseThe same redirect URL used in the authorization grant request.
Optionalcode_verifierlFDBK1ByvwTCqM2....\_N6pOq-ZThe PKCE code verifier string that the code_challenge hash was derived from in the authorization grant request

Signed Client Assertion Object header:The client assertion JWT object header contains the following parameters.

REQUIREMENTPARAMETEREXAMPLE VALUEDESCRIPTION
RequiredalgRS256Always RS256 to indicate the algorithm used.
RequiredkidcIlDeR8D4RexrZmUdKhBxMsD2bMX4l87_5JrARh4VIUThe kid (key ID) parameter of the signing key must be provided in the JOSE Header of the signed request object to indicate to the Hub which of the RP keys to be used to validate the signature.

Signed Client Assertion Object parameters: The client_assertion parameter contains the signed client assertion object, as defined in RFC 7521 Assertion Framework for OAuth 2.0. This is a signed JWT (JWS) signed with the RP's private key in compact serialized format. The signed request object includes several parameters identifying the RP client.

REQUIREMENTPARAMETEREXAMPLE VALUEDESCRIPTION
Requiredisshub-int-teamThe RP's client_id
Requiredsubhub-int-teamThe RP's client_id
Requiredaudhttp://localhost:5000/loginResponseThe token_endpoint value as defined in the Hub's openid-configuration endpoint
Requiredexp1675972884.457038The expiration time (in UNIX timestamp format) of this client assertion object
Optionaliat1675972584.457038The time (in UNIX timestamp format) at which this client assertion object was issued at
Requiredjti35a5bae49a834eb684c8c88ef7190475A unique identifier for this client assertion object

Referenced Standard(s):OpenID Connect Core 1.0 (3.1.2.1. Authentication Request)

Example Request / Response

curl -X 'POST' \
'https://https://gateway-devportal2.pp.vids.dev/oauth2/token' \
-H 'accept: application/json' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code&code=CLxk1GfMntiKySTLwv7hv-M3se69csC6xBh1KoFbToQ.FSL2GGz2VlxAr4zXwbckzdrunfzbMSlixYKQEh5KW4I&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6ImNJbERlUjhENFJleHJabVVkS2hCeE1zRDJiTVg0bDg3XzVKckFSaDRWSVUifQ.eyJhdWQiOiJodHRwczovL2dhdGV3YXktZGV2cG9ydGFsMi5wcC52aWRzLmRldi9vYXV0aDIvdG9rZW4iLCJleHAiOjE2NzU5NzI4ODQuNDU3MDM4LCJpYXQiOjE2NzU5NzI1ODQuNDU3MDM4LCJpc3MiOiJodWItaW50LXRlYW0iLCJqdGkiOiIzNWE1YmFlNDlhODM0ZWI2ODRjOGM4OGVmNzE5MDQ3NSIsInN1YiI6Imh1Yi1pbnQtdGVhbSJ9.QL169STxXxL4-Cpxokmf5C1KNAXgfJyjLa5rnrrpLnhpPdpelT_IUt1oaZ1itTFDtYhFjx1tBzBJULkNVncAX0EDCLUT_lLVGBX5bx_uSKPcJm9YOJI3HCgVYU3r_JvFiQbzr-mvWrMkvuFr8hOevu3nCNMwN3MlfWZ1t-ymgLnwy7dteN7v1MakUhDSxWY7tCIW0kJPMPfJzN8ciCBW-iJq-GZYyPF0n9t3ulHVuFxBNYQReYD0amektL4Iy5f_NqgivYIjYNKgDxTZwpKocK2BfVx2jqvGi___-y21FDos15nMLI76Sk_Bt3K_hPQc6eSDDiFWZ9_spWkKMUs5bA&client_id=hub-int-team&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2FloginResponse&code_verifier=lFDBK1ByvwTCqM2hxrGVVWcLVvjKkIeTE1JZ4ms_ZhDxPiiA7qt0YWBh8qi9_j1n7WM2-QairlqSoPWKjFEruthLJWI5gvyWIpe7bQyeMo95FE8pK0jOvs40_N6pOq-Z'
  • grant_type=authorization_code
  • code=CLxk1GfMntiKySTLwv7hv-M3se69csC6xBh1KoFbToQ.FSL2GGz2VlxAr4zXwbckzdrunfzbMSlixYKQEh5KW4I
  • client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
  • client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6ImNJbERlUjhENFJleHJabVVkS2hCeE1zRDJiTVg0bDg3XzVKckFSaDRWSVUifQ.eyJhdWQiOiJodHRwczovL2dhdGV3YXktZGV2cG9ydGFsMi5wcC52aWRzLmRldi9vYXV0aDIvdG9rZW4iLCJleHAiOjE2NzU5NzI4ODQuNDU3MDM4LCJpYXQiOjE2NzU5NzI1ODQuNDU3MDM4LCJpc3MiOiJodWItaW50LXRlYW0iLCJqdGkiOiIzNWE1YmFlNDlhODM0ZWI2ODRjOGM4OGVmNzE5MDQ3NSIsInN1YiI6Imh1Yi1pbnQtdGVhbSJ9.QL169STxXxL4-Cpxokmf5C1KNAXgfJyjLa5rnrrpLnhpPdpelT_IUt1oaZ1itTFDtYhFjx1tBzBJULkNVncAX0EDCLUT_lLVGBX5bx_uSKPcJm9YOJI3HCgVYU3r_JvFiQbzr-mvWrMkvuFr8hOevu3nCNMwN3MlfWZ1t-ymgLnwy7dteN7v1MakUhDSxWY7tCIW0kJPMPfJzN8ciCBW-iJq-GZYyPF0n9t3ulHVuFxBNYQReYD0amektL4Iy5f_NqgivYIjYNKgDxTZwpKocK2BfVx2jqvGi___-y21FDos15nMLI76Sk_Bt3K_hPQc6eSDDiFWZ9_spWkKMUs5bA

JWT header decoded:

{
  "alg": "RS256",
  "kid": "cIlDeR8D4RexrZmUdKhBxMsD2bMX4l87_5JrARh4VIU"
}

JWT body decoded:

{
  "aud": "https://gateway-devportal2.pp.vids.dev/oauth2/token",
  "exp": 1675972884.457038,
  "iat": 1675972584.457038,
  "iss": "hub-int-team",
  "jti": "35a5bae49a834eb684c8c88ef7190475",
  "sub": "hub-int-team"
}
  • client_id=hub-int-team
  • redirect_uri=http%3A%2F%2Flocalhost%3A5000%2FloginResponse
  • code_verifier=lFDBK1ByvwTCqM2hxrGVVWcLVvjKkIeTE1JZ4ms_ZhDxPiiA7qt0YWBh8qi9_j1n7WM2-QairlqSoPWKjFEruthLJWI5gvyWIpe7bQyeMo95FE8pK0jOvs40_N6pOq-Z

The response to this POST request is a JSON message with the following parameters:

  • access_token: The token to be used in the subsequent Hub UserInfo API call.
  • expires_in: number of seconds until this token expires (default is 1800 seconds).
  • id_token: A JWS containing metadata about this Hub transaction for informational purposes. Note the sub field will be a unique identifier representing the end user involved with this flow, specific to the RP/DAC.
  • scope: The OIDC scope(s) provided in the authorization request.
  • token_type: This will always be bearer to indicate that this token must be included as a Bearer token in the call to the Hub's token_endpoint.

Note that refresh_tokens are not supported. When this access_token expires or is used once, the RP/DAC will no longer be able to access the Hub's userinfo endpoint.

{
    "access_token": "ILcyQprq2MDuC9oxmiRDP0x1v7pvYh1UzhjuAB0nsyg.cfChPkBMaNxVWSQgSkauyRYgQrZTJ1skshsAWGr9Qds",
    "expires_in": 1800,
    "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6InB1YmxpYzo3N2U5MDEzNS00YTM1LTRkMmYtYTIwMi1mOTE5MzY2YTc5ZDYiLCJ0eXAiOiJKV1QifQ.eyJhdF9oYXNoIjoiblVVWFZtRTZaM2dvS2ZQUF9DTk05USIsImF1ZCI6WyJodWItaW50LXRlYW0iXSwiYXV0aF90aW1lIjoxNjc1OTcyNTE0LCJjbGllbnRfaWQiOiJodWItaW50LXRlYW0iLCJleHAiOjE2NzU5NzYxODUsImZsb3ciOiJWTUVfT05MWSIsImlhdCI6MTY3NTk3MjU4NSwiaXNzIjoiaHR0cHM6Ly9nYXRld2F5LnByZXByb2QuaHViLXZlcmlmeS5pbnRlcmFjLWlkLmNhLyIsImpvYl9pZCI6ImE1OGE5YWQxLWM2NzgtNDM5YS1iN2IzLTkxOGVjZDFjNWE4YSIsImp0aSI6IjQzY2JlZDdjLTgzZTItNDc1MC05ZDZkLTUyYTFjMzU3OTRmMSIsIm5vbmNlIjoiMDk1MzMzMTdmNDhjNDgzODk4NDFhZmRhY2M2NDU1Y2YiLCJyYXQiOjE2NzU5NzI0NzAsInNjb3BlIjoib25seVZtZSIsInNpZCI6IjVlYzVlOTY3LWZjYzctNDBkYi1iOGY1LWRhNTBiMTRmMmUzNiIsInN1YiI6ImE1OGE5YWQxLWM2NzgtNDM5YS1iN2IzLTkxOGVjZDFjNWE4YSJ9.rUtZqbpx1v-HgcbSdqRBkJfHpJrjJgXJ9N61Nk4Sg9IW2ftWcA1LONSoC_eYWnfci06LeKxD_WCNtKod1wkAggnIOWoRO3y05xlDJuIKezGI0vikSdVjgJD34myt52thInThRsceveVJrtFx8IFqivQy7UMJ1qsLUwGfDFMOjL2e6aaG1uvjn_GnN7fYGw1cpajj-favHC_eUp5zUGcTZT6GFC1TxY21yS4C6e_6zotmeWFiTYHZszkkSOG8rle1DxqiVnoQ5lUgA1OeWWc5wEZXD3ElH-9aheQlxrowu0vLZaSlbEs3tHWX6ECvf5kRjgMJjO6JsXBSfbekkuYexX1FVxHi46T7HamObRVJkJaKbQVOSwbJV4Hy7YrBP5hS6sxkRYL6SXspnwmu6J0V4EUlQqlouamFP7GftIpHowWbyTi-WOuU4C1wGA-B-EV7Ll57velDMimrVJ0as7Zu0eT94Jc1TGsaSNy1l9GuNk60hPmA-uGyO3Lz-4MZuYv2bVDRiwHUQV6MJU1TrXejZUW5hshfiA1RyD5HYXIenDW06zDW0DbKx9OWbUg44B9WQfV5h-p1wse1zEaXqP2jdK-NXb_ScbcJV2_J4icdgh4oAW0tPTeGZGSfekZpnvdzGM1kz-EE4TB62BYFmT3gS0uhpy3nY69oxx8YzYm2zp0",
    "scope": "openid onlyVme",
    "token_type": "bearer"
}