Your backend must verify the signature and claims before trusting the token.
JWKS (Public Keys)
To verify signatures, fetch OTPless public keys from:- Recommended (secure):
https://otpless.com/.well-known/jwks
RS256
signatures.You must select the key where
kid
matches the JWT header.
Example JWT ID Token
Header
Payload
Claim Reference
Claim | Type | Description | Example |
---|---|---|---|
sub | string | Subject identifier — unique ID for the user at OTPless level | "MO-1xxxcc0bf..." |
aud | string | Audience — must match your APP_ID | "XXXX1PMXXXXx1X9XXXX" |
country_code | string | Country dialing code in international format | "+91" |
auth_time | number | Epoch timestamp when authentication happened | 1758641886 |
iss | string | Issuer — must always equal https://otpless.com | "https://otpless.com" |
national_phone_number | string | Phone number without country code | "9999999999" |
phone_number_verified | boolean | Indicates whether phone number was successfully verified | true |
phone_number | string | Full phone number in E.164 format | "919999999999" |
exp | number | Expiration time (epoch seconds) — reject if token expired | 1758622386 |
iat | number | Issued-at time (epoch seconds) | 1758622086 |
token | string | Opaque reference token generated by OTPless for one time validate for s2s | "8xexxxxx54..." |
Verification Checklist
-
Signature
- Verify using RS256 with OTPless JWKS (
https://otpless.com/.well-known/jwks
).
- Verify using RS256 with OTPless JWKS (
-
Issuer (
iss
)- Must equal
https://otpless.com
.
- Must equal
-
Audience (
aud
)- Must equal
PXXXXG1XXXX1NXXYAO
.
- Must equal
-
Time claims
exp
> current time (allow ±60s skew).iat
andauth_time
optional checks.
-
App-specific checks
- Ensure
phone_number_verified: true
before granting sensitive access. - Use
sub
as the stable user identifier.
- Ensure
-
Algorithm hardening
- Accept only
RS256
. - Reject tokens with
alg: none
or unexpected algorithms.
- Accept only
Code Examples
Node.js (Express) — jose
Java (Spring Boot) — Nimbus JOSE + JWT
Python (Flask/FastAPI) — authlib
Best Practices
- Cache JWKS (5–15 minutes). Refresh when a
kid
is not found. - Always use HTTPS JWKS endpoint in production for security.
- Strictly check
iss
andaud
. - Allow a small clock skew (30–60s).
- Reject unexpected algorithms (only
RS256
). - Use
phone_number_verified
before sensitive operations. - Never trust a JWT by simply decoding — always verify signature.