Skip to content

OAuth 2.0 - Authorization Code Flow

Sesamy uses Auth0-compatible OAuth 2.0 for secure user authorization. This guide covers the Authorization Code flow for apps and websites.

Overview

The Authorization Code flow is used when you need user authorization to access Sesamy APIs. Users log in and authorize your application, and you receive an access token to make API requests on their behalf.

This flow supports:

  • Standard OAuth 2.0 Authorization Code
  • PKCE (Proof Key for Code Exchange) for enhanced security
  • Refresh tokens for long-lived sessions
  • Cookie-based sessions for custom domains

Getting Started

1. Register Your Application

  1. Log in to the Sesamy dashboard
  2. Navigate to Settings > Applications
  3. Click Create Application
  4. Select Web Application or Native Application
  5. Provide application details:
    • Name
    • Allowed Callback URLs (redirect URIs)
  6. Save your Client ID

Note

For public clients (SPAs, native apps), PKCE is required for security.

Authorization Code Flow with PKCE

PKCE (Proof Key for Code Exchange) prevents authorization code interception attacks and is recommended for all public clients.

Step 1: Generate Code Verifier and Challenge

typescript
// Generate a random string (code verifier)
function generateCodeVerifier(): string {
  const array = new Uint8Array(32);
  crypto.getRandomValues(array);
  return btoa(String.fromCharCode.apply(null, array as any))
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=/g, '');
}

// Generate code challenge from verifier
async function generateCodeChallenge(verifier: string): Promise<string> {
  const encoder = new TextEncoder();
  const data = encoder.encode(verifier);
  const digest = await crypto.subtle.digest('SHA-256', data);
  return btoa(String.fromCharCode.apply(null, new Uint8Array(digest) as any))
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=/g, '');
}

// Usage
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);

Step 2: Redirect User to Authorization Endpoint

https://token.sesamy.com/authorize?
  client_id=YOUR_CLIENT_ID&
  response_type=code&
  redirect_uri=https://yourapp.com/callback&
  scope=openid profile email&
  state=RANDOM_STATE&
  code_challenge=CODE_CHALLENGE&
  code_challenge_method=S256

Parameters:

  • client_id - Your application's client ID
  • response_type - Must be code
  • redirect_uri - Registered callback URL for your app
  • scope - Requested permissions (space-separated)
  • state - Random string to prevent CSRF attacks (REQUIRED)
  • code_challenge - Code challenge for PKCE
  • code_challenge_method - Must be S256 for SHA-256

Step 3: User Authorizes and Receives Authorization Code

After the user logs in and authorizes your application, they're redirected to your callback URL:

https://yourapp.com/callback?
  code=AUTHORIZATION_CODE&
  state=RANDOM_STATE

Important

Always verify the state parameter matches the value you sent in Step 2 to prevent CSRF attacks.

Step 4: Exchange Authorization Code for Access Token

bash
curl -X POST https://token.sesamy.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "code=AUTHORIZATION_CODE" \
  -d "code_verifier=CODE_VERIFIER" \
  -d "redirect_uri=https://yourapp.com/callback"

Response:

json
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "refresh_token_value"
}

Authorization Code Flow Without PKCE

For confidential clients (backend applications with a server), you can omit the PKCE parameters:

Step 1: Redirect User to Authorization Endpoint

https://token.sesamy.com/authorize?
  client_id=YOUR_CLIENT_ID&
  response_type=code&
  redirect_uri=https://yourapp.com/callback&
  scope=openid profile email&
  state=RANDOM_STATE

Step 2: Exchange Authorization Code for Access Token

bash
curl -X POST https://token.sesamy.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "code=AUTHORIZATION_CODE" \
  -d "redirect_uri=https://yourapp.com/callback"

Session Management

Token Refresh

When your access token expires, use the refresh token to obtain a new one:

bash
curl -X POST https://token.sesamy.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "refresh_token=REFRESH_TOKEN"

Response:

json
{
  "access_token": "NEW_ACCESS_TOKEN",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "new_refresh_token"
}

If you're using a custom domain, cookie-based sessions are automatically supported:

javascript
// Cookies are automatically set during the authorization flow
// No additional configuration needed for custom domains

Using Access Tokens

Include the access token in the Authorization header of your API requests:

bash
curl -X GET https://api.sesamy.com/client/v1/profile \
  -H "Authorization: Bearer ACCESS_TOKEN"

Scopes

Scopes define the level of access your application requests:

ScopeDescription
openidRequired for OpenID Connect
profileRead user profile information
emailAccess user email address
read:subscriptionsRead subscription data
write:subscriptionsManage subscriptions
read:entitlementsRead user entitlements
read:transactionsRead transaction history

Request only the scopes your application needs.

SDK Examples

Since Sesamy uses Auth0-compatible authentication, you can use any Auth0-compatible SDK:

typescript
import { Auth0Provider, useAuth0 } from '@auth0/auth0-react';

export default function App() {
  return (
    <Auth0Provider
      domain="token.sesamy.com"
      clientId="YOUR_CLIENT_ID"
      redirectUri={window.location.origin}
    >
      <LoginButton />
    </Auth0Provider>
  );
}

function LoginButton() {
  const { loginWithRedirect } = useAuth0();
  return (
    <button onClick={() => loginWithRedirect()}>
      Log in
    </button>
  );
}
python
from auth0.authentication import GetToken
from auth0.management import Auth0

# Get token
get_token = GetToken('token.sesamy.com')
token = get_token.authorization_code(
    client_id='YOUR_CLIENT_ID',
    client_secret='YOUR_CLIENT_SECRET',
    code='AUTHORIZATION_CODE',
    redirect_uri='https://yourapp.com/callback'
)

# Use token
auth0 = Auth0('token.sesamy.com', token['access_token'])

Security Best Practices

  1. Use PKCE: Always use PKCE for public clients (SPAs, native apps)
  2. Validate State: Always verify the state parameter to prevent CSRF attacks
  3. Use HTTPS: Always use HTTPS for all redirect URIs and callback endpoints
  4. Secure Storage: Store tokens securely (secure cookies, local storage with appropriate protections)
  5. Rotate Secrets: Regularly rotate client secrets in your dashboard
  6. Limit Scopes: Request only necessary scopes
  7. Handle Expiration: Implement token refresh logic before tokens expire

Troubleshooting

Invalid Client

  • Verify your client ID is correct
  • Ensure the application is active in your dashboard
  • For confidential clients, verify the client secret

Invalid Grant

  • Authorization code may have expired (valid for 10 minutes)
  • Code may have already been used
  • Redirect URI doesn't match the one used in authorization request

Insufficient Scope

  • Requested scope wasn't granted by user during authorization
  • Your application doesn't have permission for that scope

PKCE Invalid

  • Code verifier doesn't match code challenge
  • Code challenge method must be S256

Next Steps

  1. Limit Scopes: Request only necessary scopes
  2. Handle Expiration: Implement token refresh logic

Troubleshooting

Invalid Client

  • Verify your client ID and secret are correct
  • Ensure the OAuth application is active
  • Check that redirect URI matches exactly

Invalid Grant

  • Authorization code may have expired (valid for 10 minutes)
  • Code may have already been used
  • Redirect URI doesn't match the one used in authorization

Insufficient Scope

  • Requested scope wasn't granted by user
  • Your application doesn't have permission for that scope

Next Steps

Released under the MIT License.