Tokens and Authorization Code
| Type | Lifespan | Format |
|---|---|---|
| Authorization Code | 10 minutes | URL-safe random string |
| Access Token | 10 days | signed JWT |
| Refresh Token | 30 days | URL-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
| Claim | Type | Description |
|---|---|---|
| alg | string | Specifies the algorithm that was used to sign the token, see RFC7518 Section 3.1. The algorithms we might use are ["RS256", "ES256", "ES512", "EdDSA"]. |
| kid | string | Indicates which key was used to sign the token. |
| typ | string, always "JWT" | Indicates that this token is a JWT. |
Access Token Payload Claims
| Claim | Type | Description |
|---|---|---|
| iss | string | Identifies the principal that issued the token. The App should validate that this value matches the issuer we provided. |
| iat | int, a Unix timestamp | Identifies the time at which the token was issued. |
| nbf | int, a Unix timestamp | Identifies the time before which the token MUST NOT be accepted for processing. |
| exp | int, a Unix timestamp | Identifies 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. |
| jti | string, a UUID | Provides a unique identifier for the token. |
| aud | list[string] | Identifies the intended recipient of the token, i.e., the resource servers that may accept the token. |
| scp | list[string] | The set of scopes that the client has requested and been granted. |
| sub | string | Identifies 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_id | string | Carries 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. |