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).iatandauth_timeoptional checks.
-
App-specific checks
- Ensure
phone_number_verified: truebefore granting sensitive access. - Use
subas the stable user identifier.
- Ensure
-
Algorithm hardening
- Accept only
RS256. - Reject tokens with
alg: noneor unexpected algorithms.
- Accept only
Code Examples
Node.js (Express) — jose
Java (Spring Boot) — Nimbus JOSE + JWT
Python (Flask/FastAPI) — authlib
Go (net/http + jwx + golang-jwt)
Best Practices
- Cache JWKS (5–15 minutes). Refresh when a
kidis not found. - Always use HTTPS JWKS endpoint in production for security.
- Strictly check
issandaud. - Allow a small clock skew (30–60s).
- Reject unexpected algorithms (only
RS256). - Use
phone_number_verifiedbefore sensitive operations. - Never trust a JWT by simply decoding — always verify signature.