Authentication
This guide walks you through implementing OAuth 2.0 authorization for multi-tenant platforms integrating with Shuttle Payment Links. As a platform provider, you'll enable your merchants to securely connect their Shuttle accounts to your application.
Overview
Multi-tenant integration with Shuttle requires:
- OAuth 2.0 Setup - Configure your application as an OAuth client
- Merchant Onboarding - Guide merchants through authorization
- Token Management - Handle access and refresh tokens
- API Integration - Make authenticated requests on behalf of merchants
Platform Expectations
Your Application's Role
As a multi-tenant platform, your application will:
- Act as an OAuth client with Shuttle
- Prompt merchants to select environment before authorization (Sandbox or Live) - Default to Live
- Use the appropriate Client ID and Client Secret for the selected environment
- Manage authorization flows for multiple merchants
- Store and manage access and refresh tokens securely for each merchant
- Make API calls on behalf of authorized merchants
Merchant Experience
Your merchants will:
- Click "Connect Shuttle" in your platform
- Select environment (Sandbox or Live) - Default to Live
- Be redirected to Shuttle's authorization page
- Log in with their Shuttle credentials
- Grant permissions to your application
- Return to your platform with access granted
Implementation Steps
Step 1: OAuth Client Setup
Shuttle provides both sandbox and live environments. You'll receive two sets of OAuth credentials:
Live Environment:
- Live Client ID - For production transactions
- Live Client Secret - For production authentication
Sandbox Environment:
- Sandbox Client ID - For testing and development
- Sandbox Client Secret - For testing authentication
Platform Integration Expectation: Your platform should store all four credentials and always prompt users to choose between sandbox or live environments when connecting to Shuttle. Default to live environment, then use the appropriate Client ID and Client Secret for the selected environment throughout the OAuth flow and subsequent OAUTH operations.
Contact Shuttle support to obtain your OAuth credentials for both environments.
Step 2: Authorization Flow Implementation
Follow the complete OAuth 2.0 Authorization Code flow. For detailed technical implementation, see:
📚 Complete OAuth Guide: Multi-Tenant OAuth 2.0
Key API Endpoints:
- Authorization: /authorize - Initiate merchant authorization
- Token Exchange: /token - Exchange codes for tokens
- Token Refresh: /token - Refresh expired tokens
- Token Revocation: /revoke - Revoke tokens
- Token Introspection: /introspect - Validate tokens
Step 3: Merchant Onboarding Flow
3.1 Initiate Authorization
When a merchant wants to connect Shuttle, prompt them to select environment (default to live):
// User selects environment (default to live)
const environment = userSelectedEnvironment || 'live'; // 'live' or 'sandbox'
const clientId = environment === 'live' ? LIVE_CLIENT_ID : SANDBOX_CLIENT_ID;
// Generate authorization URL
const authUrl = `https://merchant.shuttleglobal.com/authorize?` +
`response_type=code&` +
`client_id=${clientId}&` +
`redirect_url=${encodeURIComponent(CALLBACK_URL)}&` +
`state=${merchantId}_${randomState}`;
// Redirect merchant to Shuttle
window.location.href = authUrl;3.2 Handle Authorization Callback
Process the merchant's return from Shuttle:
// In your callback handler
const { code, state } = req.query;
// Verify state and extract merchant ID
const [merchantId, originalState] = state.split('_');
if (!verifyState(originalState)) {
throw new Error('Invalid state parameter');
}
// Exchange code for tokens
const tokens = await exchangeCodeForTokens(code);
// Store tokens for this merchant
await storeMerchantTokens(merchantId, tokens);3.3 Store Merchant Tokens
Securely store tokens with merchant association:
// Example token storage
await db.merchantTokens.create({
merchantId: merchantId,
accessToken: tokens.access_token,
refreshToken: tokens.refresh_token,
expiresAt: Date.now() + (tokens.expires_in * 1000),
scopes: tokens.scope || 'default'
});Step 4: API Integration with Bearer Tokens
Once authorized, use Bearer tokens for API calls. For detailed implementation:
📚 Bearer Token Usage: Using Bearer Tokens
Making Authenticated Requests
// Example: Create payment link for a merchant
async function createPaymentLinkForMerchant(merchantId, paymentData) {
const tokens = await getMerchantTokens(merchantId);
// Check if token needs refresh
if (Date.now() >= tokens.expiresAt - 300000) { // 5 min buffer
tokens = await refreshMerchantTokens(merchantId);
}
const response = await fetch('https://app.shuttleglobal.com/c/api/payment_links', {
method: 'POST',
headers: {
'Authorization': `Bearer ${tokens.accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(paymentData)
});
if (response.status === 401) {
// Token invalid, may need re-authorization
await handleTokenError(merchantId);
throw new Error('Merchant needs to re-authorize');
}
return response.json();
}Step 5: Token Lifecycle Management
Automatic Token Refresh
Implement background token refresh:
// Refresh tokens before expiry
async function refreshMerchantTokens(merchantId) {
const currentTokens = await getMerchantTokens(merchantId);
const response = await fetch('https://merchant.shuttleglobal.com/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: currentTokens.refreshToken,
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET
})
});
const newTokens = await response.json();
// Update stored tokens
await updateMerchantTokens(merchantId, {
accessToken: newTokens.access_token,
expiresAt: Date.now() + (newTokens.expires_in * 1000)
// refresh_token stays the same
});
return newTokens;
}Handle Revoked Access
When merchants disconnect or tokens are revoked:
// Revoke tokens and clean up
async function disconnectMerchant(merchantId) {
const tokens = await getMerchantTokens(merchantId);
// Revoke refresh token (invalidates all related tokens)
await fetch('https://merchant.shuttleglobal.com/revoke', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
token: tokens.refreshToken,
token_type_hint: 'refresh_token',
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET
})
});
// Remove from your database
await deleteMerchantTokens(merchantId);
}Next Steps
- Set up OAuth credentials with Shuttle support
- Implement authorization flow using the OAuth guide
- Build token management system for your merchants
- Integrate API endpoints using Bearer tokens
- Test with sandbox merchants before production
- Certify your integration with Shuttle
For technical implementation details, refer to:
Updated 11 days ago