Credential Exchange Architecture
PehchanPe OVSE | Aadhaar App | Verifiable Credentials
System Design v1.0 — March 2026
🔐 RS256 Signing
JWT signed with RSA private key. Public key shared with UIDAI for verification. Keys rotated per CCA provisions.
⏳ Token Expiry
JWT valid for 5 minutes only. JTI claim prevents replay attacks. Each transaction gets unique txn ID.
✅ SD-JWT Verification
Response verified using UIDAI public key. Disclosure hashes validated against _sd field. PII handled per Aadhaar Act.
🔥
Firebase
Cloud Functions v2
🗄️
Firestore
NoSQL Database
🔑
RSA Keys
RS256 JWT Signing
📱
mAadhaar
Aadhaar App Intent
🛡️
SD-JWT
Verifiable Credentials
Verifier Portal Requests Credential Exchange
🏢
Verifier Portal
Web Application
⚡
generateQR CF
Build JWT Payload
🔐
RSA Private Key
JWT Signing
🗜️
qrEncoder
Base10 Encoding
QR Data Returned to Portal
🔢
Base10 String
Numeric QR Data
🔗
Intent URL
maadhaar.com/getIntent
📷
QR Code
Rendered on Portal
Cloud Function Endpoint:
generateQR — accepts hintName + scope + lang, returns txn + intentUrl + qrData + expiresAt
📱
User Scans QR Code with Aadhaar App
Cross-device credential exchange via mAadhaar intent — user consents to share identity claims
Aadhaar App Posts SD-JWT to Callback
📱
Aadhaar App
SD-JWT Response
📨
ovseCallback CF
Parse Response
🔍
sdJwtVerifier
Signature Check
📦
Credential Claims
Identity Data
Store Verified Credential & Acknowledge
📦
Verified Claims
Name, DOB, Photo...
🗄️
ovse_verifications
Firestore
✅
Aadhaar App
Acknowledged
Cloud Function Endpoint:
ovseCallback — receives txn + response (SD-JWT) + errCode + errInfo + dateTime
credential-req+jwt
Header
"alg": "RS256",
"typ": "credential-req+jwt",
"kid": "did:myaadhaarstage.uidai.gov.in:123#1"
Payload
"txn": "uuid-v4", // Unique transaction ID
"i": "credential", // Intent type
"lang": "23", // Language (English)
"sc": "00001100...01", // 63-bit scope bitmap
"pop": 1, // Proof of possession
"m": 1, // Online face auth
"ac": "aua_code", // AUA code (UIDAI assigned)
"sa": "client_id", // ⏳ Client ID (awaiting)
"cb": "https://domain/ovse/callback",
"aud": "https://myaadhaarstage.uidai.gov.in",
"iss": "https://myaadhaarstage.uidai.gov.in/v1/esignet",
"exp": iat + 300, // 5 min expiry
"iat": timestamp,
"ht": "Person Name", // Profile selection hint
"jti": "uuid-v4" // JWT unique ID
⚙️
config.ts
Centralized config — AUA codes, staging endpoints, default scope bitmap. Client ID placeholder.
New
🎯
scopeBuilder.ts
Human-readable claim names → 63-bit bitmap string per UIDAI credential spec.
New
🗜️
qrEncoder.ts
JWT encoding pipeline: ISO-8859-1 → delimiter → gzip → BigInt → Base10. Port of Python reference.
New
📷
generateQR.ts
Cloud Function: builds JWT, signs RS256, encodes to Base10, returns QR data + intent URL.
New
🔍
sdJwtVerifier.ts
SD-JWT signature verification, disclosure hash validation, credential claim extraction.
New
📨
index.ts
Enhanced callback handler — parses response, verifies SD-JWT, stores verified data in Firestore.
Modified
Cloud Function Endpoints:
generateQR · ovseCallback — All via Firebase Hosting rewrites