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. Create and open the authorization URL in browser
  2. User logs in or registers and grants permissions
  3. After it's done, user clicks a button, which redirects to your redirect URL (It can be your deeplink)
  4. Your backend exchanges the code for access and refresh tokens
  5. Your backend requests a WebApp token using the access token
  6. Display the EarthMiles WebApp in a webview (see Web App Integration)
  7. Use the access token to make API requests when needed
  8. (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: Display "See Rewards" button
    User->>Browser: Click button to redirect
    Browser->>PApp: Redirect to 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

    %% Step 5: Get WebApp Token & Display WebView
    PBackend->>EMBackend: POST /oauth/webapp-token<br/>(with access token)
    EMBackend->>PBackend: Return webapp token (1-hour expiry)
    PBackend->>PApp: Return webapp token
    PApp->>PApp: Inject token into WebView<br/>Load EarthMiles webapp

    %% Step 6: API Calls
    Note over PApp, EMBackend: Making Authenticated API Calls

    PApp->>PBackend: Request user data/operations
    PBackend->>EMBackend: GET /api/partner-api/me
    EMBackend->>PBackend: Return user data
    PBackend->>PApp: Return user data
    PApp->>PApp: Display user's Earth Miles balance

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://auth.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 will see a button to redirect back. When clicked, the user is redirected to your redirect_uri with either an authorization code or an error.

Success Response

If authorized, clicking the button redirects 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: Display EarthMiles WebApp

After successfully exchanging the authorization code for tokens, you must:

  1. Request a WebApp token using the access token:

    curl -X POST https://backend.earthmiles.app/api/oauth/webapp-token \
      -H "Authorization: Bearer ACCESS_TOKEN" \
      -H "Content-Type: application/json"
    

  2. Display the EarthMiles WebApp in a webview within your application, injecting the webapp token for authentication.

For detailed implementation instructions, see the Web App Integration Guide.

User Experience

The user should seamlessly transition from the authorization flow directly into the EarthMiles webapp within your application. This provides a unified experience without requiring the user to navigate to a separate app.

Step 5: 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 6: 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