Documentation Index Fetch the complete documentation index at: https://mintlify.com/trailbaseio/trailbase/llms.txt
Use this file to discover all available pages before exploring further.
Overview
TrailBase supports OAuth 2.0 authentication with popular identity providers. Users can sign in with their existing accounts from Google, GitHub, Microsoft, and other providers.
Supported Providers
TrailBase includes built-in support for:
Microsoft Microsoft Azure AD
Twitch Twitch Authentication
OIDC Custom OpenID Connect
Configuration
OAuth requires a public URL for redirects. Configure server.site_url in your config: server {
site_url: "https: //yourdomain.com"
}
Basic Provider Configuration
auth {
oauth_providers {
key: "google"
value {
provider_id: GOOGLE
client_id: "your-client-id.apps.googleusercontent.com"
client_secret: "your-client-secret"
}
}
oauth_providers {
key: "github"
value {
provider_id: GITLAB # Note: Use GITLAB provider_id for GitHub
client_id: "your-github-oauth-app-id"
client_secret: "your-github-oauth-app-secret"
}
}
}
Provider Setup Guides
Google OAuth
Create OAuth Client
Go to Google Cloud Console
Create a new project or select existing
Navigate to “APIs & Services” → “Credentials”
Click “Create Credentials” → “OAuth client ID”
Choose “Web application”
Configure Redirect URIs
Add authorized redirect URI: https://yourdomain.com/api/auth/v1/oauth/google/callback
Add to Configuration
auth {
oauth_providers {
key: "google"
value {
provider_id: GOOGLE
client_id: "123456789.apps.googleusercontent.com"
client_secret: "your-client-secret"
}
}
}
GitHub OAuth
Set Callback URL
https://yourdomain.com/api/auth/v1/oauth/github/callback
Configure TrailBase
auth {
oauth_providers {
key: "github"
value {
provider_id: GITLAB # Uses GitLab provider internally
client_id: "your-client-id"
client_secret: "your-client-secret"
# GitHub uses GitLab OAuth URL structure
}
}
}
Microsoft Azure AD
Register Application
Go to Azure Portal
Navigate to “Azure Active Directory” → “App registrations”
Click “New registration”
Name your application
Configure Redirect URI
Under “Authentication”, add: https://yourdomain.com/api/auth/v1/oauth/microsoft/callback
Create Client Secret
Go to “Certificates & secrets”
Click “New client secret”
Copy the secret value immediately
Add to TrailBase
auth {
oauth_providers {
key: "microsoft"
value {
provider_id: MICROSOFT
client_id: "your-application-id"
client_secret: "your-client-secret"
}
}
}
Discord
Add Redirect
https://yourdomain.com/api/auth/v1/oauth/discord/callback
Configure
auth {
oauth_providers {
key: "discord"
value {
provider_id: DISCORD
client_id: "your-client-id"
client_secret: "your-client-secret"
}
}
}
GitLab
auth {
oauth_providers {
key: "gitlab"
value {
provider_id: GITLAB
client_id: "your-application-id"
client_secret: "your-secret"
# Optional: self-hosted GitLab
# gitlab_url: "https: //gitlab.example.com"
}
}
}
Redirect URI: https://yourdomain.com/api/auth/v1/oauth/gitlab/callback
Custom OIDC Provider
For providers not explicitly supported, use OpenID Connect:
auth {
oauth_providers {
key: "custom_oidc"
value {
provider_id: OIDC_0
client_id: "your-client-id"
client_secret: "your-client-secret"
# OIDC discovery URL
oidc_discovery_url: "https: //accounts.example.com/.well-known/openid-configuration"
# Or specify endpoints manually:
# oidc_authorization_url: "https: //accounts.example.com/oauth2/auth"
# oidc_token_url: "https: //accounts.example.com/oauth2/token"
# oidc_userinfo_url: "https: //accounts.example.com/oauth2/userinfo"
}
}
}
OAuth Flow
TrailBase implements the OAuth 2.0 authorization code flow with PKCE:
┌─────────┐ ┌──────────┐
│ Browser │ │ Provider │
└────┬────┘ └────┬─────┘
│ │
│ 1. Click "Sign in with Google" │
├──────────────────────────────────► │
│ /api/auth/v1/oauth/google │
│ │
│ 2. Redirect to provider with │
│ state, code_challenge │
├──────────────────────────────────────────────────►
│ │
│ 3. User authorizes │
│ │
│ 4. Redirect with auth code │
│◄──────────────────────────────────────────────────┤
│ /api/auth/v1/oauth/google/callback │
│ │
│ 5. Exchange code for token │
│ (with code_verifier) │
├──────────────────────────────────────────────────►
│ │
│ 6. Return access token │
│◄──────────────────────────────────────────────────┤
│ │
│ 7. Fetch user profile │
├──────────────────────────────────────────────────►
│ │
│ 8. Return user data │
│◄──────────────────────────────────────────────────┤
│ │
│ 9. Create/login user, set session cookies │
│◄────────────────────────────────────────── │
│ │
Security Features
PKCE (Proof Key for Code Exchange)
TrailBase uses PKCE for all OAuth flows:
// From crates/core/src/auth/oauth/state.rs
pub ( crate ) struct OAuthState {
/// OAuth CSRF protection
pub state : String ,
/// PKCE code verifier
pub code_verifier : String ,
/// Optional redirect URL after successful auth
pub redirect_url : Option < String >,
}
State Parameter
Prevents CSRF attacks by validating state:
// State is stored in encrypted JWT cookie
let state = jwt_encode ( OAuthState {
state : random_string (),
code_verifier : generate_code_verifier (),
redirect_url : Some ( "/dashboard" . to_string ()),
});
User Linking
Users can link multiple OAuth providers to one account:
-- User table tracks OAuth provider associations
CREATE TABLE _user (
id BLOB PRIMARY KEY ,
email TEXT UNIQUE ,
verified INTEGER NOT NULL DEFAULT 0 ,
provider_id INTEGER , -- OAuth provider ID
provider_user_id TEXT , -- User ID from provider
-- ...
);
API Endpoints
Initiate OAuth Flow
GET /api/auth/v1/oauth/{provider}
Redirects user to provider’s authorization page.
Query Parameters:
redirect_url (optional): Where to redirect after successful auth
Example:
< a href = "/api/auth/v1/oauth/google?redirect_url=/dashboard" >
Sign in with Google
</ a >
OAuth Callback
GET /api/auth/v1/oauth/{provider}/callback
Handles the callback from OAuth provider. Automatically processes:
Validates state parameter
Exchanges authorization code for access token
Fetches user profile
Creates or updates user
Sets session cookies
Redirects to redirect_url or default page
List Available Providers
GET /api/auth/v1/oauth/providers
Response:
{
"providers" : [
{
"name" : "google" ,
"display_name" : "Google"
},
{
"name" : "github" ,
"display_name" : "GitHub"
}
]
}
Frontend Integration
<! DOCTYPE html >
< html >
< head >
< title > Sign In </ title >
< style >
.oauth-button {
display : inline-flex ;
align-items : center ;
padding : 12 px 24 px ;
margin : 8 px ;
border : 1 px solid #ddd ;
border-radius : 4 px ;
text-decoration : none ;
color : #333 ;
background : white ;
font-family : system-ui ;
}
.oauth-button:hover {
background : #f5f5f5 ;
}
.oauth-button img {
width : 20 px ;
height : 20 px ;
margin-right : 12 px ;
}
</ style >
</ head >
< body >
< h1 > Sign In </ h1 >
< a href = "/api/auth/v1/oauth/google" class = "oauth-button" >
< img src = "/icons/google.svg" alt = "Google" >
Sign in with Google
</ a >
< a href = "/api/auth/v1/oauth/github" class = "oauth-button" >
< img src = "/icons/github.svg" alt = "GitHub" >
Sign in with GitHub
</ a >
< a href = "/api/auth/v1/oauth/microsoft" class = "oauth-button" >
< img src = "/icons/microsoft.svg" alt = "Microsoft" >
Sign in with Microsoft
</ a >
</ body >
</ html >
React Component
import React , { useEffect , useState } from 'react' ;
interface Provider {
name : string ;
display_name : string ;
}
export function OAuthButtons () {
const [ providers , setProviders ] = useState < Provider []>([]);
useEffect (() => {
fetch ( '/api/auth/v1/oauth/providers' )
. then ( res => res . json ())
. then ( data => setProviders ( data . providers ));
}, []);
const handleOAuthLogin = ( provider : string ) => {
const redirectUrl = encodeURIComponent ( window . location . pathname );
window . location . href = `/api/auth/v1/oauth/ ${ provider } ?redirect_url= ${ redirectUrl } ` ;
};
return (
< div >
{ providers . map ( provider => (
< button
key = { provider . name }
onClick = { () => handleOAuthLogin ( provider . name ) }
className = "oauth-button"
>
Sign in with { provider . display_name }
</ button >
)) }
</ div >
);
}
User Profile Data
OAuth providers return different user information:
// From crates/core/src/auth/oauth/mod.rs
pub struct OAuthUser {
pub provider_user_id : String , // Provider's user ID
pub provider_id : OAuthProviderId ,
pub email : Option < String >,
pub verified : bool ,
pub name : Option < String >,
pub avatar_url : Option < String >,
}
Admin API
List Available OAuth Providers
curl -H "Authorization: Bearer $ADMIN_TOKEN " \
https://api.example.com/_/admin/oauth/providers
Response:
{
"providers" : [
{
"id" : 2 ,
"name" : "google" ,
"display_name" : "Google"
},
{
"id" : 3 ,
"name" : "github" ,
"display_name" : "GitHub"
}
]
}
Provider Implementation
Each provider implements the OAuthProvider trait:
// From crates/core/src/auth/oauth/mod.rs
pub trait OAuthProvider : Send + Sync {
fn name ( & self ) -> & str ;
fn provider ( & self ) -> OAuthProviderId ;
fn settings ( & self ) -> Result < OAuthClientSettings , AuthError >;
fn oauth_scopes ( & self ) -> Vec < & ' static str >;
async fn get_user (
& self ,
token_response : & TokenResponse
) -> Result < OAuthUser , AuthError >;
}
Troubleshooting
Error: “redirect_uri_mismatch”Solution: Ensure the callback URL in your provider settings exactly matches:https://yourdomain.com/api/auth/v1/oauth/{provider}/callback
Check:
Protocol (http vs https)
Domain name
Port (if not 80/443)
Path (including /callback)
Invalid client credentials
Error: “invalid_client”Solution:
Verify client_id is correct
Ensure client_secret hasn’t expired
Check provider dashboard for any issues
Regenerate credentials if necessary
Error: User data missing (email, name, etc.)Solution: Check OAuth scopes. TrailBase requests:
Google: openid email profile
GitHub: user:email
Discord: identify email
Ensure these scopes are approved in your OAuth app settings.
Best Practices
Use HTTPS in production
OAuth requires HTTPS for redirect URIs in production. Use certificates from Let’s Encrypt or your provider.
Rotate secrets regularly
Periodically regenerate client secrets and update your configuration.
Request minimal scopes
Only request the OAuth scopes your application actually needs.
Handle provider outages
Implement fallback authentication methods (email/password) in case OAuth providers are unavailable.
Test thoroughly
Test OAuth flows in development before deploying to production.
Next Steps
Email Configure email for fallback auth
Custom Endpoints Build custom auth flows
Object Storage Store user avatars
Jobs Scheduler Sync OAuth data