Authentication API
Blockia Pay uses a passwordless authentication system based on passkeys (WebAuthn) and JWT sessions. The flow is non-custodial, secure, and user-friendly.
Flow Overview
- Registration (
POST /v1/identity/register): User submits email. User is created with statusREGISTERED. - Email Verification (
POST /v1/email-verification/verify): User submits OTP from email. On success, user status becomesWALLET_SETUP_PENDINGand a JWT is issued as an httpOnly cookie.- Resend OTP:
POST /v1/email-verification/resend
- Resend OTP:
- Wallet Setup (Passkey Registration): Passkey registration is handled as
part of the authentication flow. When a user is eligible, the backend issues
a WebAuthn challenge via
/v1/auth/optionsand verifies the response via/v1/auth/verify. On success, the user's smart contract wallet is deployed and status becomesACTIVE. - Authentication (Login):
POST /v1/auth/options: User submits email. If eligible, receives WebAuthn challenge and allowed credentials. If not, response indicates next required step (email verification or wallet setup).POST /v1/auth/verify: User submits signed WebAuthn response. On success, JWT is issued as httpOnly cookie.
- Session Management:
GET /v1/auth/me: Get current user info (requires JWT).POST /v1/auth/logout: Logout and clear session.
- Google OAuth (Optional):
GET /v1/auth/google/authorize→GET /v1/auth/google/callback: On success, JWT is issued as cookie.
WebAuthn Passkey Authentication
1. Request Authentication Options
POST /v1/auth/options
Content-Type: application/json
{
"email": "user@example.com"
}
Response (ready to authenticate):
{
"success": true,
"requiresCompletion": false,
"challengeId": "ch_...",
"challenge": "base64-encoded-challenge",
"timeout": 60000,
"rp": { "id": "blockia.pay", "name": "Blockia Pay" },
"allowCredentials": [
{
"id": "base64-credential-id",
"type": "public-key",
"transports": ["internal"]
}
],
"userVerification": "preferred"
}
Response (email verification required):
{
"success": false,
"reason": "EMAIL_VERIFICATION_REQUIRED",
"userId": "user_...",
"userStatus": "REGISTERED",
"redirectTo": "/email-verification",
"emailVerificationSent": false
}
Response (wallet setup required):
{
"success": false,
"reason": "WALLET_SETUP_REQUIRED",
"userId": "user_...",
"userStatus": "WALLET_SETUP_PENDING",
"redirectTo": "/wallet-setup"
}
2. Browser WebAuthn
Use the browser's WebAuthn API with the challenge:
const credential = await navigator.credentials.get({ publicKey: challenge });
3. Verify Authentication
POST /v1/auth/verify
Content-Type: application/json
{
"challengeId": "ch_...",
"email": "user@example.com",
"authenticationResponse": { ... }
}
Response (success):
{
"verified": true,
"user": {
"id": "user_...",
"email": "user@example.com",
"status": "ACTIVE",
"createdAt": "2024-01-01T10:00:00.000Z",
"updatedAt": "2024-01-01T10:00:00.000Z",
"hasWallet": true,
"walletAddress": "0x123..."
}
}
Response (failure):
{
"verified": false,
"message": "Authentication failed"
}
Google OAuth Authentication
1. Initiate OAuth
GET /v1/auth/google/authorize
Redirects to Google. Rate limit: 10 requests per 60 seconds.
2. OAuth Callback
GET /v1/auth/google/callback?state=...&code=...
On success, sets authToken cookie and redirects to dashboard.
Session Management
Get Current User
GET /v1/auth/me
Cookie: authToken=...
Response:
{
"id": "user_...",
"email": "user@example.com",
"status": "ACTIVE",
"createdAt": "2024-01-01T10:00:00.000Z",
"updatedAt": "2024-01-01T10:00:00.000Z",
"hasWallet": true,
"walletAddress": "0x123...",
"wallet": { "address": "0x123...", "network": "base-sepolia" },
"permissions": ["CREATE_PAYMENT_LINK", "VIEW_TRANSACTIONS", "MANAGE_WALLET"]
}
Get User Status
GET /v1/auth/status
Cookie: authToken=...
Response:
{
"status": "ACTIVE",
"completedSteps": [
"registration",
"email_verification",
"wallet_setup",
"activation"
]
}
Logout
POST /v1/auth/logout
Cookie: authToken=...
Response:
{
"success": true,
"message": "Logged out successfully"
}
Authentication Cookies
- Name:
authToken - Type: httpOnly, secure (production), sameSite=strict
- Duration: 1 hour
- Set automatically after successful authentication
User Statuses
- REGISTERED: Registered, must verify email
- WALLET_SETUP_PENDING: Email verified, must set up wallet
- ACTIVE: Wallet set up, full access
Permissions are assigned based on status.
Error Handling
- All endpoints return structured error responses with clear messages and codes.
- Example:
{ "verified": false, "message": "Authentication failed" } - Validation errors for missing/invalid data.
Security
- Hardware-backed biometric authentication (WebAuthn)
- Cross-device passkey sync (iCloud, Android)
- Rate limiting on OAuth endpoints
- CSRF protection via SameSite cookies
- Session invalidation on logout
Development Mode
NODE_ENV=development: Secure cookie flag is disabled