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
- Log in to the Sesamy dashboard
- Navigate to Settings > Applications
- Click Create Application
- Select Web Application or Native Application
- Provide application details:
- Name
- Allowed Callback URLs (redirect URIs)
- 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
// 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=S256Parameters:
client_id- Your application's client IDresponse_type- Must becoderedirect_uri- Registered callback URL for your appscope- Requested permissions (space-separated)state- Random string to prevent CSRF attacks (REQUIRED)code_challenge- Code challenge for PKCEcode_challenge_method- Must beS256for 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_STATEImportant
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
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:
{
"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_STATEStep 2: Exchange Authorization Code for Access Token
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:
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:
{
"access_token": "NEW_ACCESS_TOKEN",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "new_refresh_token"
}Cookie Sessions (Custom Domains)
If you're using a custom domain, cookie-based sessions are automatically supported:
// Cookies are automatically set during the authorization flow
// No additional configuration needed for custom domainsUsing Access Tokens
Include the access token in the Authorization header of your API requests:
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:
| Scope | Description |
|---|---|
openid | Required for OpenID Connect |
profile | Read user profile information |
email | Access user email address |
read:subscriptions | Read subscription data |
write:subscriptions | Manage subscriptions |
read:entitlements | Read user entitlements |
read:transactions | Read transaction history |
Request only the scopes your application needs.
SDK Examples
Since Sesamy uses Auth0-compatible authentication, you can use any Auth0-compatible SDK:
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>
);
}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
- Use PKCE: Always use PKCE for public clients (SPAs, native apps)
- Validate State: Always verify the
stateparameter to prevent CSRF attacks - Use HTTPS: Always use HTTPS for all redirect URIs and callback endpoints
- Secure Storage: Store tokens securely (secure cookies, local storage with appropriate protections)
- Rotate Secrets: Regularly rotate client secrets in your dashboard
- Limit Scopes: Request only necessary scopes
- 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
- API Keys - Learn about Management API credentials
- JWT Tokens - Understanding and validating access tokens
- API Reference - Explore available API endpoints
- Limit Scopes: Request only necessary scopes
- 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
- JWT Tokens - Learn about JWT authentication
- API Reference - Explore API endpoints