OAuth Provider Token Refresh
Access OAuth provider APIs (Google, GitHub, etc.) on behalf of your users.
Access OAuth provider APIs (Google, GitHub, etc.) on behalf of your users.
Overview
When users sign in with OAuth, providers like Google give us two tokens:
- Access Token - Short-lived (1 hour), used to call provider APIs
- Refresh Token - Long-lived, used to get new access tokens
Volcano stores refresh tokens (encrypted) and can refresh access tokens on demand, allowing you to call provider APIs on behalf of your users.
Use Cases
Google APIs
// Get user's Google Drive files
POST /auth/oauth/google/refresh-token
// Returns fresh access token
// Use token to call Google Drive API
GET https://www.googleapis.com/drive/v3/files
Authorization: Bearer {fresh_access_token}GitHub APIs
// Get user's GitHub repositories
POST /auth/oauth/github/refresh-token
// Returns fresh access token
// Use token to call GitHub API
GET https://api.github.com/user/repos
Authorization: Bearer {fresh_access_token}Microsoft Graph
// Access user's OneDrive
POST /auth/oauth/microsoft/refresh-token
// Call Microsoft Graph API
GET https://graph.microsoft.com/v1.0/me/drive/root/childrenAPI Reference
Refresh Provider Token
POST /auth/oauth/{provider}/refresh-token
Authorization: Bearer {user_access_token}Refreshes the OAuth provider's access token using stored refresh token.
Parameters:
provider- google, github, microsoft, or apple
Response:
{
"message": "Provider token refreshed successfully",
"provider": "google",
"expires_in": 3600
}Errors:
401- Not authenticated404- Provider not linked to user400- No refresh token available
Get Current Provider Token
GET /auth/oauth/{provider}/token
Authorization: Bearer {user_access_token}Gets valid access token for provider. Automatically refreshes if expired.
Response:
{
"access_token": "ya29.a0...",
"expires_in": 3600,
"provider": "google"
}Setup
1. Request Offline Access Scope
To get refresh tokens, you must request the appropriate scope:
Google:
{
"provider": "google",
"scopes": ["openid", "email", "profile", "https://www.googleapis.com/auth/drive.readonly"]
}Add offline_access or specific API scopes.
GitHub:
{
"scopes": ["read:user", "user:email", "repo"]
}Microsoft:
{
"scopes": ["openid", "email", "profile", "offline_access", "Files.Read"]
}2. Tokens Stored Automatically
When user signs in via OAuth, Volcano automatically stores:
- Provider's refresh token (encrypted with AES-256)
- Token expiration time
- Provider user ID
3. Refresh When Needed
// In your application
async function callGoogleAPI(endpoint) {
// 1. Refresh provider token
await fetch(`/auth/oauth/google/refresh-token`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${userAccessToken}` }
});
// 2. Get fresh token (already refreshed)
const tokenResp = await fetch(`/auth/oauth/google/token`, {
headers: { 'Authorization': `Bearer ${userAccessToken}` }
});
const { access_token } = await tokenResp.json();
// 3. Call Google API
const data = await fetch(`https://www.googleapis.com/drive/v3${endpoint}`, {
headers: { 'Authorization': `Bearer ${access_token}` }
});
return data.json();
}Security
Token Encryption
All provider tokens encrypted with AES-256-GCM:
-- Database storage (encrypted)
auth_providers.refresh_token = 'base64-encrypted-data'
-- NOT plaintext:
auth_providers.refresh_token ≠ '1//actual-refresh-token'Protection mechanisms:
| Feature | Description |
|---|---|
| Database compromise | Tokens remain protected even if database is accessed |
| AES-256 encryption | NSA Suite B compliant encryption |
| GCM mode | Tamper detection via authenticated encryption |
| Consistent encryption | Same encryption as OAuth client secrets |
Access control
Who can refresh tokens:
| Allowed | Blocked |
|---|---|
| The user who linked the provider | Other users' tokens |
| Authenticated requests (valid access token) | Cross-project requests |
| Tokens tied to correct project | Unauthenticated requests |
Token Lifecycle
Storage:
- Refresh token stored when user signs in via OAuth
- Encrypted before database INSERT
- Decrypted only when needed
Refresh:
- Used to get fresh access token from provider
- New refresh token may be returned (rotation)
- Expiration tracked automatically
Deletion:
- Deleted when provider unlinked
- Deleted when user deleted (CASCADE)
- Deleted when project deleted (CASCADE)
Limitations
Provider Support
| Provider | Refresh Token | Notes |
|---|---|---|
| Yes | Requires offline_access or API scopes | |
| GitHub | Yes | Refresh tokens supported |
| Microsoft | Yes | Requires offline_access scope |
| Apple | Limited | Apple tokens have different refresh flow |
Token Availability
Refresh tokens are only available if:
- Provider supports refresh tokens
- Appropriate scopes requested (offline_access)
- User granted permission during OAuth flow
If no refresh token:
- User must re-authenticate via OAuth
- Error: "no refresh token available for provider"
Testing
Test Token Storage
# Create user with OAuth
# Link Google provider
# Store refresh token
# Check database (should be encrypted)
psql $DATABASE_URL -c "
SELECT user_id, provider,
substring(refresh_token, 1, 20) as token_preview
FROM auth_providers
WHERE provider = 'google';
"
# Should see encrypted data, NOT plaintextTest Token Refresh
# Refresh Google token
curl -X POST https://api.volcano.dev/auth/oauth/google/refresh-token \
-H "Authorization: Bearer USER_ACCESS_TOKEN"
# Response:
{
"message": "Provider token refreshed successfully",
"provider": "google",
"expires_in": 3600
}Error Handling
"no refresh token available for provider"
Cause: Provider doesn't have refresh token stored
Solutions:
- User must re-authenticate via OAuth
- Ensure correct scopes requested (
offline_access) - Check provider supports refresh tokens
"provider not linked to user"
Cause: User hasn't linked this OAuth provider
Solution: Link provider first via /auth/oauth/{provider}/link
"failed to refresh provider token"
Causes:
- Refresh token expired or revoked by provider
- OAuth config changed (client_id/secret)
- Provider service down
Solution: User must re-authenticate via OAuth
Best Practices
Request minimal scopes
Only request the scopes you need:
// Recommended
{
"scopes": ["email", "profile", "drive.readonly"]
}
// Not recommended
{
"scopes": ["email", "profile", "drive", "calendar", "contacts", "..."]
}Handle token refresh failures
async function callProviderAPI(provider, endpoint) {
try {
// Try to refresh token
await refreshProviderToken(provider);
const token = await getProviderToken(provider);
return await callAPI(endpoint, token);
} catch (error) {
if (error.message.includes('no refresh token')) {
// User must re-authenticate
redirectToOAuth(provider);
}
throw error;
}
}Cache access tokens
// Don't refresh on every request
const tokenCache = new Map();
async function getValidProviderToken(provider) {
const cached = tokenCache.get(provider);
if (cached && cached.expiresAt > Date.now()) {
return cached.token; // Use cached token
}
// Refresh and cache
const { access_token, expires_in } = await refreshProviderToken(provider);
tokenCache.set(provider, {
token: access_token,
expiresAt: Date.now() + (expires_in * 1000) - 60000 // 1 min buffer
});
return access_token;
}Provider-Specific Notes
Refresh Token Availability:
- First authorization: Refresh token provided
- Subsequent authorizations: No refresh token (reuse existing)
- To force new refresh token: Add
prompt=consentto auth URL
Scopes for APIs:
- Drive:
https://www.googleapis.com/auth/drive.readonly - Calendar:
https://www.googleapis.com/auth/calendar.readonly - Gmail:
https://www.googleapis.com/auth/gmail.readonly
GitHub
Refresh Token:
- Supported since 2022
- No special scope needed
- Tokens don't expire unless revoked
Useful Scopes:
repo- Access repositoriesread:org- Read org datagist- Manage gists
Microsoft
Refresh Token:
- Requires
offline_accessscope - Works with personal accounts and Azure AD
Useful Scopes:
Files.Read- OneDriveMail.Read- OutlookCalendars.Read- Calendar
Related Documentation
- OAuth Providers - Provider setup
- OAuth Integration Guide - Integration
- OAuth API Reference - API docs
OAuth / SSO Provider Integration
Volcano Hosting supports third-party OAuth providers (Google, GitHub, Microsoft, Apple) for user authentication.
Authentication
Volcano provides a complete authentication system for your applications. Each project has its own isolated set of users, tokens, and configuration.