Kulcare Docs
Developer

PHR (Personal Health Records) - ABHA Login Guide

This guide documents the PHR ABHA (Ayushman Bharat Health Account) login implementation, including the patient app login flow, API endpoints, and integration patterns.

Overview

The patient app supports three ABHA login methods:

  1. Login with Mobile - OTP sent to registered mobile
  2. Login with ABHA Address - Password or OTP authentication
  3. Login with ABHA Number - OTP to 14-digit ABHA number

Architecture

System Components

Authentication Flow Overview

Login Methods

1. Login with Mobile (Section 6.3)

API Endpoints:

EndpointMethodDescription
/login/mobile/request_otpPOSTSend OTP to mobile
/login/mobile/verify_otpPOSTVerify OTP, returns ABHAs
/login/verify_userPOSTSelect ABHA, generate session

2. Login with ABHA Address (Section 12.1 / Password)

API Endpoints:

EndpointMethodDescription
/login/abha_address/searchPOSTGet available auth methods
/login/abha_address/verify_passwordPOSTVerify with password

3. Login with ABHA Number (Section 6.2)

Note: ABHA Number login may return "Invalid LoginId" in ABDM sandbox.

API Endpoints:

EndpointMethodDescription
/login/abha_number/request_otpPOSTSend OTP to ABHA number
/login/abha_number/verify_otpPOSTVerify OTP

API Reference

Common Headers

All PHR API requests must include:

Content-Type: application/json
Authorization: Bearer <gateway_token>
REQUEST-ID: <uuid>
TIMESTAMP: <ISO8601 format>

Request Format

{
  "abha_address": "john123@sbx",
  "password": "Addval@A621"
}

Response Format

Success:

{
  "success": true,
  "data": {
    "abha_token": "eyJhbG...",
    "abha_refresh_token": "eyJ...",
    "abha_expires_in": 1800,
    "abha_profile": {
      "abha_address": "john123@sbx",
      "abha_number": "12-3456-7890-1234",
      "name": "John Doe",
      "mobile": "9876543210"
    },
    "kulcare_session": { ... }
  }
}

Error:

{
  "success": false,
  "error": "Error message from ABDM or Kulcare"
}

Error Codes

CodeMessageDescription
ABDM-1006Invalid LoginIdInvalid ABHA address or number
ABDM-1016Invalid TimestampRequest timestamp format incorrect
ABDM-9999Invalid PasswordPassword verification failed
ABDM-9999Invalid ABHA AddressABHA address format incorrect

Frontend Implementation

Login Flow State Machine

Component Architecture

Zustand Store Structure

interface PhrOtpState {
  method: 'mobile' | 'abha_address' | 'abha_number';
  loginId: string;
  txnId: string;
  abhaToken: string;
  abhaList: AbhaAccount[];
  otpType?: 'mobile' | 'aadhaar';
}

interface AuthState {
  user: User | null;
  session: KulcareSession | null;
  phrOtpState: PhrOtpState | null;
  // ...
  phrSignIn: (session: KulcareSession) => void;
  setPhrOtpState: (state: PhrOtpState) => void;
  clearPhrOtpState: () => void;
}

Backend Implementation

Service Architecture

Key Services

GenerateKulcareSessionService

This service creates a Kulcare session from ABHA verification data:

PhrRequest Logging

All outbound API calls are logged to the phr.requests table:

Security Considerations

RSA Encryption

All sensitive data (mobile numbers, OTPs, passwords) must be encrypted using RSA:

Token Handling

  1. Gateway Token: Obtained from Phr::FetchGatewayTokenV3 for ABDM API calls
  2. ABHA Token: Received from ABDM after successful verification
  3. Kulcare Session: Generated JWT for authenticated sessions

Data Privacy

  • Patient ABHA data is stored with phone_verified: true flag
  • All API requests are logged for audit purposes
  • PII is not logged in production

Environment Configuration

Development (Sandbox)

# config/credentials/development.yml
abdm_phr_host: https://abhasbx.abdm.gov.in/abha/api/v3/phr/app
abdm_gateway_host_v3_modes: https://dev.abdm.gov.in/cm

Production

# config/credentials/production.yml
abdm_phr_host: https://phr.abdm.gov.in/api/phr/app/v3
abdm_gateway_host_v3_modes: https://cm.abdm.gov.in

Keys

RSA public keys for encryption are stored in:

config/keys/abdm_public_auth_number.pem

Testing

API Testing with curl

Search ABHA Address:

curl -X POST http://localhost:3000/phr/login/abha_address/search \
  -H "Content-Type: application/json" \
  -d '{"abha_address": "john123@sbx"}'

Verify Password:

curl -X POST http://localhost:3000/phr/login/abha_address/verify_password \
  -H "Content-Type: application/json" \
  -d '{"abha_address": "john123@sbx", "password": "your_password"}'

Mobile OTP Flow:

# Step 1: Send OTP
curl -X POST http://localhost:3000/phr/login/mobile/request_otp \
  -H "Content-Type: application/json" \
  -d '{"mobile": "9876543210"}'

# Step 2: Verify OTP
curl -X POST http://localhost:3000/phr/login/mobile/verify_otp \
  -H "Content-Type: application/json" \
  -d '{"mobile": "9876543210", "otp": "123456", "txn_id": "your_txn_id"}'

Troubleshooting

Common Issues

IssueCauseSolution
"Invalid Timestamp"Timestamp format incorrectUse Time.now.utc.iso8601(3)
"Missing Credentials"No Authorization headerAdd Bearer <token> header
"Invalid Password"Wrong password or encodingCheck RSA encryption
"Invalid ABHA Address"abhaAddress not encryptedOnly encrypt password, not address
401 UnauthorizedGateway token expiredRefresh gateway token

Log Analysis

All PHR API calls are logged in phr.requests table:

SELECT * FROM phr.requests
WHERE action = 'verify_password'
ORDER BY created_at DESC
LIMIT 10;

File Structure

Backend

backend/domains/phr/
├── controllers/login/logins_controller.rb
├── routes.rb
├── models/phr_request.rb
├── services/
│   ├── login/
│   │   ├── mobile/
│   │   │   ├── request_otp.rb
│   │   │   └── verify_otp_service.rb
│   │   ├── abha_address/
│   │   │   ├── search_abha_address_service.rb
│   │   │   └── verify_password_service.rb
│   │   └── generate_kulcare_session_service.rb
│   └── abha/
│       └── encrypt_phr_data.rb
└── services/fetch_gateway_token_v3.rb

Frontend

patient/src/
├── features/auth/
│   ├── components/
│   │   ├── LoginForm.tsx
│   │   ├── AbhaOtpVerification.tsx
│   │   └── ProtectedRoute.tsx
│   └── schemas/
│       └── abha-login.schema.ts
├── services/
│   └── phr-auth.service.ts
├── stores/
│   └── auth.store.ts
├── types/
│   ├── phr.types.ts
│   └── auth.types.ts
├── constants/
│   ├── api.ts
│   └── routes.ts
└── api/
    └── phr-client.ts

On this page