🔐 OAuth 2.0 Authentication Guide
Earth Miles uses OAuth 2.0 with PKCE (Proof Key for Code Exchange) for secure authentication. This guide covers the complete authentication flow.
Authorization Flow
The OAuth 2.0 authorization flow consists of the following steps:
- Redirect the user to our web application (with webview in mobile apps)
- User logs in or registers and grants permissions
- User is redirected to EarthMiles app, and we trigger a request to your redirect url with an authorization code
- Your backend exchanges the code for access and refresh tokens
- Use the access token to make API requests when needed
- (optional) Refresh the token when it expires
sequenceDiagram
participant User as 👤 User
participant PApp as 📱 Partner App
participant PBackend as ⚙️ Partner Backend
participant Browser as � Browser/WebView
participant EMWebApp as 🖥️ EarthMiles WebApp
participant EMBackend as 🌍 EarthMiles Backend
Note over User, EMBackend: OAuth 2.0 with PKCE Authorization Flow
%% Step 1: Initialize OAuth Flow
User->>PApp: Clicks on the "Connect" button
PApp->>PBackend: Request starting the process
PBackend->>PBackend: Generate URL including 'client_id',<br/> 'code_verifier', 'code_challenge' & 'state'<br/>
PBackend->>PApp: Return authorization URL<br/>with PKCE parameters
PApp->>Browser: Open WebView/Browser<br/>and navigate to authorization URL
%% Step 2: User Authorization
Browser->>EMWebApp: Open and show the EarthMiles WebApp
EMWebApp->>Browser: Display login/registration page
User->>EMWebApp: Enter credentials & grant permissions<br/>(login or register)
EMWebApp->>EMBackend: Validate user credentials<br/>Process authorization request
EMBackend->>EMBackend: Authenticate user<br/>Generate authorization code
%% Step 3: Authorization Response
EMWebApp->>Browser: Redirect user to the EarthMiles app or AppStore/GPlay
EMBackend->>PBackend: Trigger redirect_uri with code & state parameters
PBackend->>PBackend: Verify state parameter<br/>(CSRF protection)
%% Step 4: Token Exchange
PBackend->>EMBackend: POST /oauth/token
EMBackend->>EMBackend: Validate code_verifier<br/>against code_challenge
EMBackend->>PBackend: Return access and refresh token
PBackend->>PBackend: Store tokens securely
PBackend->>PApp: Authentication success response
%% Step 5: API Calls
Note over PApp, EMBackend: Making Authenticated API Calls
PApp->>PBackend: Request user data/operations
PBackend->>EMBackend: GET /api/me
EMBackend->>PBackend: Return user data
PBackend->>PApp: Return user data
Prerequisites
Before starting, ensure you have:
- Partner account with Earth Miles
- Client credentials (
client_id
,client_secret
) - Registered redirect URIs
Step 1: Authorization Request
Redirect users to the authorization endpoint to start the flow:
Required Parameters
Parameter | Required | Description |
---|---|---|
client_id |
✅ | Your registered client ID |
redirect_uri |
✅ | Must match registered redirect URI |
scope |
✅ | Space-separated scopes: miles:read miles:write |
state |
✅ | Random string to prevent CSRF attacks |
response_type |
✅ | Must be code |
code_challenge |
✅ | PKCE code challenge (see PKCE Guide) |
code_challenge_method |
✅ | Must be S256 |
Example Authorization URL
Once the parameters are generated, redirect the user to:
https://webapp.earthmiles.app/oauth/authorize?
client_id=your_client_id&
redirect_uri=https://your-app.com/callback&
scope=miles:read%20miles:write&
state=random_state_string&
response_type=code&
code_challenge=CODE_CHALLENGE&
code_challenge_method=S256
Step 2: Handle Authorization Response
After the user authorizes, they get redirected to EarthMiles application and we trigger a call to your redirect_uri
with either an authorization code or an error.
Success Response
If authorized, the user is redirected to your redirect_uri
with:
Error Response
If authorization fails:
https://your-app.com/callback?
error=access_denied&
error_description=The%20user%20denied%20the%20request&
state=random_state_string
Always verify the state
parameter matches what you sent to prevent CSRF attacks.
Step 3: Exchange Code for Tokens
Use the authorization code to get access and refresh tokens:
Request Body
{
"grant_type": "authorization_code",
"code": "AUTHORIZATION_CODE",
"client_id": "your_client_id",
"client_secret": "your_client_secret",
"code_verifier": "ORIGINAL_CODE_VERIFIER"
}
Success Response
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "refresh_token_value",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "miles:read miles:write"
}
Step 4: Making Authenticated Requests
Include the access token in the Authorization header:
curl https://backend.earthmiles.app/api/partner-api/award-points \
-H "Authorization: Bearer ACCESS_TOKEN"
Step 5: Refreshing Tokens
When the access token expires, use the refresh token to get a new one:
Request Body
{
"grant_type": "refresh_token",
"refresh_token": "refresh_token_value",
"client_id": "your_client_id"
}
Response
{
"access_token": "new_access_token",
"refresh_token": "new_refresh_token",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "miles:read miles:write"
}
Security Considerations
- Always use HTTPS in production
- Store tokens securely - never in localStorage or client-side storage
- Implement PKCE correctly (see PKCE Implementation Guide)
- Validate state parameter to prevent CSRF attacks
- Handle token expiration gracefully with refresh tokens