GitHub OAuth Setup
Secure your llms.py deployment with GitHub OAuth authentication
Features
Secure your llms.py deployment with GitHub OAuth authentication and optional user access restrictions.
- ✅ GitHub OAuth 2.0 integration
- ✅ Secure session management
- ✅ CSRF protection with state tokens
- ✅ User profile display with avatar
- ✅ Logout functionality
- ✅ Optional user access restrictions
- ✅ Environment variable support
Setup Instructions
1. Create a GitHub OAuth App
- Go to GitHub Settings → Developer settings → OAuth Apps
- Click "New OAuth App"
- Fill in the application details:
- Application name:
llms.py(or your preferred name) - Homepage URL:
http://localhost:8000 - Authorization callback URL:
http://localhost:8000/auth/github/callback
- Application name:
- Click "Register application"
- Note down your Client ID
- Click "Generate a new client secret" and note down the Client Secret
For production deployments, use your actual domain instead of localhost.
2. Configure Environment Variables
Set the following environment variables:
export GITHUB_CLIENT_ID="your_github_client_id_here"
export GITHUB_CLIENT_SECRET="your_github_client_secret_here"
# Optional - Comma or space separated list of allowed users
export GITHUB_USERS="octocat mythz"For permanent configuration, add these to your shell profile (~/.bashrc, ~/.zshrc, etc.).
3. Configure llms.json
Enable OAuth in your ~/.llms/llms.json:
{
"auth": {
"enabled": true,
"github": {
"client_id": "$GITHUB_CLIENT_ID",
"client_secret": "$GITHUB_CLIENT_SECRET",
"redirect_uri": "http://localhost:8000/auth/github/callback",
"restrict_to": "$GITHUB_USERS"
}
}
}Note: The $ prefix indicates environment variables that will be automatically expanded at runtime.
Optional: The restrict_to field can be omitted to allow any GitHub user to authenticate.
4. Start the Server
llms --serve 8000Or with Docker:
docker run -p 8000:8000 \
-e GITHUB_CLIENT_ID="$GITHUB_CLIENT_ID" \
-e GITHUB_CLIENT_SECRET="$GITHUB_CLIENT_SECRET" \
-e GITHUB_USERS="$GITHUB_USERS" \
-e GROQ_API_KEY="$GROQ_API_KEY" \
ghcr.io/servicestack/llms:latestUsage
Signing In
- Navigate to
http://localhost:8000 - Click "Sign in with GitHub"
- Authorize the application on GitHub
- You'll be redirected back to the application, now authenticated
Signing Out
- Click on your avatar in the top-right corner
- A dropdown menu will appear showing your profile info
- Click "Sign Out"
Restricted Access
If restrict_to is configured, only specified GitHub users can access the application:
{
"auth": {
"github": {
"restrict_to": "octocat mythz demisbellot"
}
}
}Users not in the list will see an "Access Denied" message after authenticating.
Configuration
Full Configuration Example
{
"auth": {
"enabled": true,
"github": {
"client_id": "$GITHUB_CLIENT_ID",
"client_secret": "$GITHUB_CLIENT_SECRET",
"redirect_uri": "http://localhost:8000/auth/github/callback",
"restrict_to": "$GITHUB_USERS"
}
},
"providers": {
...
}
}Disable Authentication
To disable authentication:
{
"auth": {
"enabled": false,
"github": { ... }
}
}Or remove the entire auth section.
Production Configuration
For production, update the redirect_uri:
{
"auth": {
"github": {
"client_id": "$GITHUB_CLIENT_ID",
"client_secret": "$GITHUB_CLIENT_SECRET",
"redirect_uri": "https://yourdomain.com/auth/github/callback",
"restrict_to": "$GITHUB_USERS"
}
}
}Also update the callback URL in your GitHub OAuth App settings.
Architecture
Server Endpoints
New authentication endpoints:
GET /auth/github- Initiates GitHub OAuth flowGET /auth/github/callback- Handles OAuth callbackGET /auth/session- Validates session tokenPOST /auth/logout- Ends user session
Session Management
- Sessions stored in-memory (
g_sessionsdictionary) - Session tokens are 32-byte URL-safe random strings
- Sessions expire after 24 hours
- CSRF protection using state tokens (expire after 10 minutes)
Authentication Flow
- User clicks "Sign in with GitHub"
- Redirected to
/auth/github - Server redirects to GitHub OAuth authorization
- User authorizes on GitHub
- GitHub redirects to
/auth/github/callbackwith code - Server exchanges code for access token
- Server fetches user info from GitHub API
- Server creates session and redirects to
/?session=TOKEN - Client validates session and stores user info
- User is authenticated
Session Data Structure
{
"userId": "12345678",
"userName": "octocat",
"displayName": "The Octocat",
"profileUrl": "https://avatars.githubusercontent.com/u/583231",
"email": "[email protected]",
"sessionToken": "abc123...",
"created": 1234567890.123
}Security
CSRF Protection
- State tokens are generated for each OAuth flow
- State tokens are validated on callback
- Expired state tokens (>10 minutes) are automatically cleaned up
Session Security
- Session tokens are cryptographically random (32 bytes)
- Sessions expire after 24 hours
- Expired sessions are automatically cleaned up
- Session tokens transmitted via URL parameter (initial) and HTTP header (subsequent)
Best Practices
- Use HTTPS in Production: Always use TLS for production deployments
- Rotate Secrets: Regularly rotate GitHub OAuth client secrets
- Environment Variables: Never commit credentials to version control
- Minimal Scope: OAuth app only requests minimal required scopes
- Session Expiry: 24-hour expiry balances security and convenience
Troubleshooting
"GitHub OAuth not configured" error
- Ensure
GITHUB_CLIENT_IDandGITHUB_CLIENT_SECRETare set - Restart the server after setting environment variables
- Verify environment variables are expanded in config
"Invalid state parameter" error
- OAuth flow took longer than 10 minutes
- Try the sign-in process again
"Invalid or expired session" error
- Session expired (24-hour limit)
- Sign in again to create a new session
"Access Denied" error
- Your GitHub username is not in the
restrict_tolist - Contact the administrator to be added
- Or remove
restrict_toto allow all users
Callback URL mismatch
- Ensure
redirect_uriinllms.jsonmatches GitHub OAuth App settings exactly - For localhost:
http://localhost:8000/auth/github/callback - For production:
https://yourdomain.com/auth/github/callback
Production Considerations
Persistent Sessions
For production with multiple instances, consider:
- Redis: Store sessions in Redis for sharing across instances
- Database: Use PostgreSQL or similar for session storage
- Sticky Sessions: Configure load balancer for sticky sessions
HTTPS/TLS
Always use HTTPS in production:
- Certificate: Obtain SSL/TLS certificate (Let's Encrypt)
- Reverse Proxy: Use nginx or Traefik with TLS termination
- HSTS: Enable HTTP Strict Transport Security
- Secure Cookies: Use secure flag for session cookies
Monitoring
Monitor authentication:
- Failed Attempts: Track failed login attempts
- Active Sessions: Monitor active session count
- Session Duration: Track how long users stay authenticated
- Access Logs: Log authentication events
Docker Deployment
With docker compose:
version: '3.8'
services:
llms:
image: ghcr.io/servicestack/llms:latest
ports:
- "8000:8000"
environment:
- GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID}
- GITHUB_CLIENT_SECRET=${GITHUB_CLIENT_SECRET}
- GITHUB_USERS=${GITHUB_USERS}
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
- GROQ_API_KEY=${GROQ_API_KEY}
volumes:
- llms-data:/home/llms/.llms
restart: unless-stopped
volumes:
llms-data:Create .env file:
GITHUB_CLIENT_ID=your_client_id
GITHUB_CLIENT_SECRET=your_client_secret
GITHUB_USERS=octocat mythz
OPENROUTER_API_KEY=sk-or-...
GROQ_API_KEY=gsk_...Start:
docker compose up -d