How to verify FID token

Struct of a normal token

A JWT is combined from 3 parts, separated by period ‘.’ character. All three parts are base64url-coded (not base64) of actual data.

base64url(header).base64url(payload).base64url(signature)

header: JSON object reposent signature algorithm, keyid. Example:

{
  "alg": "RS256",
  "kid": "A15AAA8208D664A3C3D7A6CE1F04501381048B29RS256",
  "x5t": "oVqqggjWZKPD16bOHwRQE4EEiyk",
  "typ": "at+jwt"
}

Fid currently uses the “RS256” algorithm.

payload: JSON object with JWT claims. Example:

{
  "iss": "https://id.ftech.ai",
  "nbf": 1659408417,
  "iat": 1659408417,
  "exp": 1659412017,
  "aud": "https://id.ftech.ai/resources",
  "scope": [
	"email",
	"fid-api:id",
	"openid",
	"phone",
	"profile",
	"offline_access"
  ],
  "amr": [
	"pwd"
  ],
  "client_id": "stress.test",
  "sub": "1002",
  "auth_time": 1659408417,
  "idp": "local",
  "sid": "51be0330396d498a89f26e705b8f0421"
}

signature: Signature of first two parts of the JWT, using algorithm and key from header. With “RS256” algorithm, signature can be computed as follow:

signature = RSA( SHA256( base64url(header).base64url(payload) ))

RFC: https://datatracker.ietf.org/doc/html/rfc7519#section-3

Step to verify JWT

  • Preparing: Get certificates from authority. In OIDC, certificates can be obtained from an jwks url, which defined from oidc configuration. Example:

  • Authority: ${domain}

Product: https://id.ftech.ai

Develop: https://id-dev.ftech.ai

Example jwks:

An authority can have multiple certificates and can be changed at most 2 times per day. A recommended way is to cached jwks and refresh once per 1 hour.

Using firebase/php-jwt library to cached public keys: https://github.com/firebase/php-jwt#using-cached-key-sets

Attn: data from jwks are in x509 certificate format. Some library only accept public keys, verifier can extract key from certificate using openssl library: https://www.php.net/manual/en/function.openssl-pkey-get-public.php

  • Check expiration time: check if “exp” claim in payload is not later than current time,

  • Check authority: check if “iss” claim in payload is a valid authority. The list of valid authorities can be configured before,

  • Verify signature:

    • Check if algorithm is RS256,

    • Check if “kid” field in header is from certificates cache. If the authority has multiple certificates, pick the one with same “kid”,

    • Use the certificate to verify signature, i.e check if

SHA256(base64url(header).base64url(payload)) == RSA-Decode(signature)

Last updated