Skip to content

🔐 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:

  1. Redirect the user to our web application (with webview in mobile apps)
  2. User logs in or registers and grants permissions
  3. User is redirected to EarthMiles app, and we trigger a request to your redirect url with an authorization code
  4. Your backend exchanges the code for access and refresh tokens
  5. Use the access token to make API requests when needed
  6. (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:

https://your-app.com/callback?
  code=AUTHORIZATION_CODE&
  state=random_state_string

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:

POST https://backend.earthmiles.app/api/oauth/token

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:

POST https://backend.earthmiles.app/api/oauth/token

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