Complete ASA/CDAC Onboarding-Ready UIDAI Virtual Endpoint for Auth v2.5 and e-KYC.
Explore APIThe UIDAI Stub provides a simulated environment for testing Aadhaar-based authentication and e-KYC workflows. It enforces strict v2.5 shape checks and follows the official UIDAI specification for request/response payloads.
Enforces mandatory elements: <Uses>, <Meta>,
<Skey>, <Data>, <Hmac>, and
<Signature>.
Correctly derives e-KYC from the <Rad> element, which must contain the
Base64-encoded Auth XML.
Built-in audit trails with automatic redaction of sensitive fields (PID, Skey, Hmac) to ensure security compliance.
Designed specifically to pass ASA/CDAC onboarding reviews with deterministic response toggles.
Simulates the mandatory Vault service that replaces Aadhaar numbers with Reference Keys for secure storage.
Moving from a local application to a UIDAI-integrated system involves a multi-step workflow. Here is the complete lifecycle of a transaction:
http://localhost:11100 (standard RD port)./keys.php generate_keys.php.The frontend must call the RD Service to capture biometric data. This results in an encrypted
PID block.
// Example JS to call RD Service
fetch('http://localhost:11100/rd/capture', {
method: 'CAPTURE',
body: '<PidOptions ver="1.0">...</PidOptions>'
}).then(res => res.text()).then(xml => {
// Send this PID XML to your backend
});
Construct the official Auth v2.5 XML. This is the core document that identifies the resident.
Required Blocks:
<Uses>: Defines what you are matching (pi, pa, bio, otp).<Meta>: Device and environment metadata.<Skey>: Encrypted session key used for PID.<Data>: The actual encrypted PID block.<Hmac>: Hash of the PID for integrity.To request e-KYC data, you do not call the Auth endpoint directly. Instead, you wrap the Auth XML inside a Kyc request.
// PHP Example
$fullAuthXml = "<Auth...>...</Auth>";
$base64Rad = base64_encode($fullAuthXml);
$kycRequest = '<Kyc ver="2.5" ra="F" rc="Y" lr="N" de="N" pfr="Y">
<Rad>' . $base64Rad . '</Rad>
</Kyc>';
The stub returns a <Resp> block. Inside the textContent is the
Base64-encoded KycRes.
// 1. Decode the outer Resp payload
$kycResXml = base64_decode($respContent);
// 2. Parse KycRes to get User Data
// Payload contains: <Poi> (Name/DOB), <Poa> (Address), <Pht> (Photo)
UIDAI mandates that you do not store Aadhaar numbers in your own DB. Instead, you send the
Aadhaar to the Vault and get a Reference Key.
// Call the Vault Endpoint
$payload = json_encode(["aadhaar" => "999988887777"]);
$response = curl_post("/uidai/vault", $payload);
// Output: {"reference_key": "4e1a-8b2c-..."}
You can test the stub instantly using your terminal. Use these commands to verify the endpoints on the live server.
Verify the stub is alive and responding.
curl -X GET https://agribid.auction/index.php/health
Exchange a raw Aadhaar number for a secure Reference Key.
curl -X POST https://agribid.auction/index.php/uidai/vault \
-H "Content-Type: application/json" \
-d '{"aadhaar": "999988887777"}'
Retrieve the original Aadhaar number using a Reference Key.
curl -X POST https://agribid.auction/index.php/uidai/vault/retrieve \
-H "Content-Type: application/json" \
-d '{"reference_key": "YOUR_REFERENCE_KEY"}'
Test the core authentication logic with a sample XML payload.
curl -X POST https://agribid.auction/index.php/uidai/auth \
-H "Content-Type: text/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?><Auth uid="999988887777" tid="registered" ac="public" sa="public" ver="2.5" txn="STUB_TXN_001" lk="STUB_LK"><Uses pi="y" pa="y" pfa="n" bio="y" bt="FMR" otp="n" pin="n"/><Meta udc="device123" pip="127.0.0.1" lot="P" lov="18.52,73.85"/><Skey ci="20251222">BASE64_SKEY</Skey><Data type="X">BASE64_PID</Data><Hmac>BASE64_HMAC</Hmac><Signature>EXISTENCE_CHECK_ONLY</Signature></Auth>'
Use the interactive Swagger UI below to test the endpoints directly from your browser. Note that for Auth/KYC endpoints, you should provide valid XML payloads.
Once you pass the onboarding review with this stub, transitioning to the official ASA/CDAC production environment requires minimal changes:
Replace StubCryptoProvider with a real implementation that uses openssl
for RSA/AES and XMLDSig (C14N).
Replace dummy files in /keys with official Certificates and Private Keys issued by
your ASA.
Point your backend to the ASA Gateway URL (e.g.,
https://production-gateway.asa.in/kyc).
To pass the UIDAI audit, your application must adhere to the following security standards. This stub already implements the following:
AuditLogger in this stub automatically redacts
Skey, Data, and Hmac. Ensure your production logs do the
same.If you're not a cryptography expert, don't worry! Here is how you connect your website/app to this stub in plain English.
Think of keys as your ATM PIN. You don't write
them in your code; you put them in a "Secret Folder" called .env.
# Your .env file
UIDAI_PRIVATE_KEY_PATH="/var/www/keys/stub_private.pem"
UIDAI_CERT_PATH="/var/www/keys/stub_public.crt"
REDIS_URL="redis://127.0.0.1:6379"
Apps speak JSON (Simple), but UIDAI speaks XML (Complex). Your backend acts as the translator.
Getting data from UIDAI is slow/expensive. Once you get the XML response, decrypt it and save it in Redis for 10-15 minutes.
kyc_999988887777.Finally, take that complex XML result, turn it back into a simple JSON list (Name, Gender, Photo URL), and send it to your Mobile App.
App (JSON) ⇢ Backend (Convert to XML) ⇢
Encrypt ⇢ UIDAI Stub (Process) ⇢ Receive XML ⇢
Decrypt ⇢ Save to Redis ⇢ Return JSON to App
This stub simulates standard UIDAI error codes. Below are the most common ones you'll encounter during testing.
| Code | Meaning | Condition (Stub Logic) |
|---|---|---|
0 |
Success | Auth processed successfully |
100 |
Invalid Aadhaar | UID not 12 digits |
101 |
Invalid XML | Malformed tags or missing blocks |
102 |
Invalid Version | ver attribute is not 2.5 |
105 |
Invalid Signature | Missing or invalid XMLDSig block |
122 |
Biometric Mismatch | Returned when force_auth_success is false
|
| Code | Meaning | Trigger |
|---|---|---|
540 |
Missing Rad | The <Rad> element is empty or missing
|
541 |
Invalid Version | Kyc ver is not 2.5 |
542 |
No Consent | Resident consent rc is not 'Y' |
546 |
Auth in Rad Failed | The Auth XML inside Rad failed basic validation |
547 |
KYC Not Requested | Uses pi or pa are not set to 'y'
|
The stub behavior is driven by config.php. You can customize the response data here.
// Example config.php
"force_auth_success" => true,
"force_kyc_success" => true,
"sample_kyc" => [
"uid" => "999988887777",
"name" => "STUB USER",
"dob" => "1999-01-01",
"address" => [...]
]