Tokens and Authorization Code

Tokens and Authorization Code

TypeLifespanFormat
Authorization Code10 minutesURL-safe random string
Access Token10 dayssigned JWT
Refresh Token30 daysURL-safe random string

Authorization Codes and Refresh Tokens are randomly generated strings with HMAC and only the Authorization Server can understand them.

Access Token

The Access Token returned by the Token Endpoint is a signed JSON Web Token (JWT), which means it is also a JWS.

An Access Token example and its decoded claims is shown below.

eyJhbGciOiJSUzI1NiIsImtpZCI6Im1mNXZkMWR6IiwidHlwIjoiSldUIn0.eyJhdWQiOlsiYW1zLm9hdXRoMi5oay50ZXN0Il0sImNsaWVudF9pZCI6IjNlOGE3YTBjMzljZTRhYTRhZDI2NTViNzBhNWQ5OTVlIiwiZXhwIjoxNjQxMTA4MTQ2LCJpYXQiOjE2NDAyNDQxNDYsImlzcyI6Imh0dHBzOi8vdGVzdC1vYXV0aC50aWdlcmZpbnRlY2guY29tL29hdXRoMiIsImp0aSI6IjJkNjE1ZGMzLWNiYjEtNDRmOC04ZDg3LTk2MGM5NjdmYjAxNiIsIm5iZiI6MTY0MDI0NDE0Niwic2NwIjpbInV1aWQiLCJvZmZsaW5lIl0sInN1YiI6IjUzNDg5NTA1NTEyNzQifQ.KtxkVd30tNczk7hZc6M5ihdgNven8DIG9hgPmGXmnRLwxdDaPLvZsjZHGt0_39Y1o2R9wHUb_DscXwa07qCFJOhNy6IF2f8i_9cqmiqesDRNG7XSHbSu_8s-_JOL07JsiWk-bG292zp-keX0f82gd29ugUv2q5nL1beuIcZBBiMvLruUhloNnGX8ZETJ5Ej33cP9d7PcxeIgtWnsv2u9-B69PpTrf1qTxVmEobWpY3jp_abI90OLSpR7btGlmbRPdHEMrC2JFiJEjlWNItp-PQZCbK9VEkbwacZ3JgM09f7B5ck0sPkDV3-45AQ3go-zvUkkrJdJgIFcYJSnYJBkbg
{
  "alg": "RS256",
  "kid": "mf5vd1dz",
  "typ": "JWT"
}.{
  "aud": [
    "ams.oauth2.hk.test"
  ],
  "client_id": "3e8a7a0c39ce4aa4ad2655b70a5d995e",
  "exp": 1641108146,
  "iat": 1640244146,
  "iss": "https://test-oauth.tigerfintech.com/oauth2",
  "jti": "2d615dc3-cbb1-44f8-8d87-960c967fb016",
  "nbf": 1640244146,
  "scp": [
    "uuid",
    "offline"
  ],
  "sub": "5348950551274"
}.[Signature]

Verify Access Token

Before utilizing the sub claim, the App should verify the token's signature using the public keys provided,
and validate that the kid and alg claims of the token match those of the keys.
The App should also verify several claims as explained in the Payload Claims section.

The following code snippet serves as an example of how to verify Access Token.

Please note that we recommend not hardcoding issuer and client_id in the function.

import json
from typing import Dict, Any

from jwcrypto import jwk, jwt
from jwcrypto.common import base64url_decode


def extract_kid(token: str) -> str:
    """

    :param token: JWE or JWS
    :return: kid
    :raises ValueError:
    """
    header_segment = token.partition('.')[0]
    header_data = base64url_decode(header_segment)
    header = json.loads(header_data)

    if not isinstance(header, dict):
        raise ValueError('Header must be a json object')

    return header.get('kid', None)


def verify_jwt(token: str, public_key_list: Dict[str, Dict[str, Any]]) -> Dict[str, Any]:
    """
    :param token: JWT
    :param public_key_list: the public keys we provided
    :return: claims
    """
    kid: str = extract_kid(token)

    public_key_to_use: Dict[str, Any] = public_key_list[kid]

    public_key: jwk.JWK = jwk.JWK()
    public_key.import_from_pem(public_key_to_use['pem'].encode())

    alg: str = public_key_to_use['alg']
    issuer: str = "https://oauth.itiger.com/oauth2"
    client_id: str = "your client id"

    jwt_obj = jwt.JWT(
        algs=[alg],
        check_claims=dict(
            exp=None,  # check whether exp is later than current time or not
            nbf=None,  # check whether nbf is earlier than current time or not
            iss=issuer,  # check whether the token is issued by us
            client_id=client_id,  # check whether the token is issued to you
        )
    )
    jwt_obj.deserialize(token, public_key)
    return json.loads(jwt_obj.claims)

Claims in the Access Token

Access Token Header Claims

ClaimTypeDescription
algstringSpecifies the algorithm that was used to sign the token, see RFC7518 Section 3.1.
The algorithms we might use are ["RS256", "ES256", "ES512", "EdDSA"].
kidstringIndicates which key was used to sign the token.
typstring, always "JWT"Indicates that this token is a JWT.

Access Token Payload Claims

ClaimTypeDescription
issstringIdentifies the principal that issued the token.
The App should validate that this value matches the issuer we provided.
iatint, a Unix timestampIdentifies the time at which the token was issued.
nbfint, a Unix timestampIdentifies the time before which the token MUST NOT be accepted for processing.
expint, a Unix timestampIdentifies the expiration time on or after which the token MUST NOT be accepted for processing.
Please note that, the token may also be rejected by the resource servers before this time, due to token revocation.
jtistring, a UUIDProvides a unique identifier for the token.
audlist[string]Identifies the intended recipient of the token, i.e., the resource servers that may accept the token.
scplist[string]The set of scopes that the client has requested and been granted.
substringIdentifies the principal that is the subject of the token.
client:{client_id} if the token represents the App;
Unique user identifier if the token represents a user and the uuid scope has requested and been GRANTED.
client_idstringCarries the client identifier of the OAuth 2.0 client that requested the token.
The App should validate that this value is the same as the App's client_id.