OAuth 2.0 Authentication Flow
Version: 1.0.0
Last Updated: 18-11-2025
Status: Production Ready
Table of Contents
- Overview
- OAuth 2.0 Provider Capabilities
- Supported Scopes
- OAuth Client Registration
- Complete OAuth Flow
- Token Refresh Flow
- Token Responsibility Matrix
- Security Features
- Error Handling
- Integration Examples
- User Consent Management
- Best Practices
- Related Documentation
Overview
ChainGuard provides a full OAuth 2.0 authorization server that enables third-party applications to authenticate users and access user data with explicit consent. This document describes the complete OAuth 2.0 authorization code flow, including authentication, 2FA, scope management, and token handling.
OAuth 2.0 Provider Capabilities
ChainGuard Backend Server acts as a full OAuth 2.0 authorization server with the following capabilities:
- Authorization Code Flow: Standard OAuth 2.0 authorization code flow
- Token Refresh: Long-lived refresh tokens for token renewal
- Scope-Based Access Control: Fine-grained permission system
- Client Authentication: client_id + client_secret authentication
- Userinfo Endpoint: Standard OAuth userinfo endpoint
- PKCE Support: (Planned) Code verifier/challenge for enhanced security
- State Parameter: CSRF protection
Supported Scopes
ChainGuard supports the following OAuth scopes:
| Scope | Description | Data Returned |
|---|---|---|
profile | User profile information | Name, email, user ID |
email | Email address | Email address |
wallets | Linked wallet addresses | Array of wallet addresses |
kyc | KYC verification status | KYC status, verification level (if applicable) |
Scope Management:
- Users approve scopes during OAuth consent screen
- Users can revoke scopes at any time via OAuth Portal
- Clients can only access data within approved scopes
- Scope changes require user re-consent
OAuth Client Registration
Client Registration Process
Clients are registered in the ChainGuard system with:
- client_id: Unique identifier for the application
- client_secret: Secret key for server-to-server authentication
- redirect_uris: Allowed callback URLs (whitelist-based)
- scopes: Available scopes the client can request
- Application Name: Display name shown to users
- Application Description: Description shown on consent screen
Security Requirements
- Client Secret: Must be kept server-side only, never exposed to frontend
- Redirect URI Validation: Only registered redirect URIs are accepted
- HTTPS Required: All redirect URIs must use HTTPS in production
- State Parameter: Required for CSRF protection
Complete OAuth Flow
OAuth 2.0 Authorization Code Flow
Step-by-Step Flow
Step 1: User Initiates Login
Client Frontend (CL-FE)
↓
User clicks "Login with ChainGuard"
↓
Redirect to ChainGuard OAuth Portal
URL Format:
https://module.chain-fi.io/oauth/authorize?
client_id={CLIENT_ID}
&redirect_uri={REDIRECT_URI}
&response_type=code
&scope={SCOPES}
&state={RANDOM_STATE}
Step 2: User Authentication
ChainGuard OAuth Portal
↓
1. User enters email/password
2. Backend validates credentials
3. User completes 2FA (wallet-based signature via Mobile App)
4. Session established with JWT tokens
Authentication Methods:
- Email/password authentication
- Wallet-based 2FA (EIP-712 signature)
- Session management via HttpOnly cookies
Step 3: OAuth Consent Screen
ChainGuard OAuth Portal
↓
1. Display consent screen with:
- Application name and description
- Requested scopes
- Data that will be shared
2. User reviews and approves/denies
3. User can modify scope selection (if allowed)
Consent Screen Features:
- Clear scope descriptions
- Data sharing transparency
- User control over permissions
- Revocation capabilities
Step 4: Authorization Code Issuance
ChainGuard Backend Server
↓
1. Validate user consent
2. Generate authorization code
3. Store code with expiration (10 minutes)
4. Associate code with client_id and scopes
↓
ChainGuard OAuth Portal
↓
Redirect to client redirect_uri with:
- code={AUTHORIZATION_CODE}
- state={ORIGINAL_STATE}
Authorization Code Properties:
- Single-use only
- 10-minute expiration
- Tied to specific client_id and redirect_uri
- Associated with approved scopes
Step 5: Token Exchange
Client Backend (CL-BE)
↓
POST to ChainGuard Backend:
/oauth/token
{
grant_type: "authorization_code",
code: {AUTHORIZATION_CODE},
redirect_uri: {REDIRECT_URI},
client_id: {CLIENT_ID},
client_secret: {CLIENT_SECRET}
}
↓
ChainGuard Backend Server
↓
1. Validate authorization code
2. Verify client_id and client_secret
3. Check redirect_uri matches
4. Generate access token and refresh token
5. Return tokens to client backend
Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "def50200a1b2c3d4e5f6...",
"scope": "profile email wallets"
}
Step 6: Token Storage
Client Backend (CL-BE)
↓
1. Store access_token and refresh_token (server-side only)
2. Create client session cookie for user
3. Never expose tokens to frontend
Token Storage Requirements:
- Server-side storage only
- Secure storage (encrypted at rest)
- Never in browser localStorage or sessionStorage
- Never sent to client frontend
Step 7: User Data Retrieval
Client Frontend (CL-FE)
↓
Request user profile
↓
Client Backend (CL-BE)
↓
GET /oauth/userinfo
Authorization: Bearer {access_token}
↓
ChainGuard Backend Server
↓
1. Validate access token
2. Check token expiration
3. Verify scopes
4. Return user data within approved scopes
Userinfo Response:
{
"sub": "user_id",
"name": "John Doe",
"email": "user@example.com",
"wallets": [
"0x1234...5678",
"0xabcd...efgh"
]
}
Token Refresh Flow
Token Refresh Sequence
When to Refresh
Access tokens are short-lived (typically 1 hour). When a token expires:
Client Backend (CL-BE)
↓
1. Detect expired access token (401 response)
2. Use refresh_token to get new access token
↓
POST /oauth/token
{
grant_type: "refresh_token",
refresh_token: {REFRESH_TOKEN},
client_id: {CLIENT_ID},
client_secret: {CLIENT_SECRET}
}
↓
ChainGuard Backend Server
↓
1. Validate refresh token
2. Verify client credentials
3. Issue new access token
4. Optionally issue new refresh token
Refresh Token Properties:
- Long-lived (typically 30 days)
- Revocable by user
- Server-side only
- Single-use (if rotation enabled)
Token Responsibility Matrix
| Token Type | Holder | Storage Location | Exposure Risk |
|---|---|---|---|
| Authorization Code | Client Backend (temporary) | Server memory | Low (10-min expiration) |
| Access Token | Client Backend only | Server-side storage | None (never sent to frontend) |
| Refresh Token | Client Backend only | Server-side storage | None (never sent to frontend) |
| client_id | Client Backend | Server-side storage | Low (public identifier) |
| client_secret | Client Backend only | Server-side storage | High (must be protected) |
| Client Session Cookie | Client Backend → Frontend | HttpOnly cookie | Minimal (client-controlled) |
Key Principles:
- Tokens never exposed to frontend environments
- Server-to-server exchanges only
- HttpOnly cookies prevent XSS attacks
- Refresh tokens stored server-side only
Security Features
CSRF Protection
State Parameter:
- Required in authorization request
- Random, unguessable value
- Validated on callback
- Prevents cross-site request forgery
Client Secret Protection
Security Requirements:
- Never exposed to frontend
- Server-side storage only
- Encrypted at rest
- Rotated periodically
- Never logged or transmitted insecurely
Token Security
Access Token:
- Short-lived (1 hour default)
- Bearer token format
- HTTPS only transmission
- Scope-limited access
Refresh Token:
- Long-lived (30 days default)
- Server-side only
- Revocable by user
- Single-use (if rotation enabled)
Scope Validation
Scope Enforcement:
- Tokens contain approved scopes
- API endpoints validate scopes
- Users can revoke scopes anytime
- Scope changes require re-consent
Error Handling
Common Error Scenarios
Invalid Authorization Code:
- Code expired (10 minutes)
- Code already used
- Code doesn't match client_id
- Response: 400 Bad Request
Invalid Client Credentials:
- Invalid client_id
- Invalid client_secret
- Mismatched redirect_uri
- Response: 401 Unauthorized
Invalid Token:
- Token expired
- Token revoked
- Invalid token format
- Response: 401 Unauthorized
Insufficient Scope:
- Token doesn't have required scope
- Scope revoked by user
- Response: 403 Forbidden
Integration Examples
Client Backend Integration
Token Exchange (Node.js/Express):
const response = await fetch('https://api.chain-fi.io/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
grant_type: 'authorization_code',
code: authorizationCode,
redirect_uri: redirectUri,
client_id: clientId,
client_secret: clientSecret,
}),
});
const tokens = await response.json();
// Store tokens server-side
User Data Retrieval:
const userInfo = await fetch('https://api.chain-fi.io/oauth/userinfo', {
headers: {
'Authorization': `Bearer ${accessToken}`,
},
});
const userData = await userInfo.json();
Token Refresh:
const response = await fetch('https://api.chain-fi.io/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
grant_type: 'refresh_token',
refresh_token: refreshToken,
client_id: clientId,
client_secret: clientSecret,
}),
});
const newTokens = await response.json();
User Consent Management
Consent Screen
Displayed Information:
- Application name and description
- Requested scopes with descriptions
- Data that will be shared
- User's ability to modify scopes
User Actions:
- Approve all requested scopes
- Approve selected scopes only
- Deny access
- Review application details
Scope Revocation
User Control:
- Users can revoke scopes at any time via OAuth Portal
- Revocation immediately invalidates related tokens
- Clients receive 401 Unauthorized on next API call
- Clients must re-authenticate to regain access
Revocation Process:
- User accesses OAuth Portal
- Navigates to Application Access Control
- Disables specific scopes
- Backend invalidates related tokens
- Client receives error on next API call
Best Practices
For Client Developers
Security:
- Never expose client_secret to frontend
- Store tokens server-side only
- Use HTTPS for all communications
- Validate state parameter
- Implement token refresh logic
User Experience:
- Request only necessary scopes
- Provide clear application description
- Handle errors gracefully
- Implement proper logout flow
Token Management:
- Monitor token expiration
- Implement automatic token refresh
- Handle token revocation
- Store tokens securely
For ChainGuard Users
Privacy:
- Review requested scopes carefully
- Only approve necessary permissions
- Revoke access when no longer needed
- Monitor application access in portal
Security:
- Use strong passwords
- Enable 2FA
- Review activity history regularly
- Report suspicious applications
Related Documentation
- Project Architecture - Complete project overview
- System Overview - System architecture details
- Security Framework - OAuth security controls
- System Components - Backend Server and OAuth Portal details
Document Version: 1.0.0
Last Updated: 18-11-2025
Status: Production Ready