Supabase supports over 20 OAuth providers for social authentication. Users can sign in with their existing accounts from popular platforms.
Supported Providers
Supabase supports these OAuth providers:
- Google
- GitHub
- GitLab
- Bitbucket
- Azure (Microsoft)
- Apple
- Facebook
- Discord
- Twitch
- Twitter
- Slack
- Spotify
- LinkedIn
- And many more…
Basic OAuth Sign In
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
})
if (error) {
console.error('OAuth error:', error.message)
}
Provider Configuration
Before using OAuth, configure each provider in your Supabase dashboard:
Open Dashboard
Navigate to Authentication > Providers in your Supabase project
Enable Provider
Toggle on the provider you want to use (e.g., Google, GitHub)
Add Credentials
Enter your OAuth client ID and secret from the provider’s developer console
Configure Redirect URL
Add the callback URL to your provider’s app settings:https://<project-ref>.supabase.co/auth/v1/callback
Google OAuth
Setup Google OAuth
- Go to Google Cloud Console
- Create a new project or select existing
- Enable Google+ API
- Create OAuth 2.0 credentials
- Add authorized redirect URI:
https://<project-ref>.supabase.co/auth/v1/callback
- Copy Client ID and Secret to Supabase dashboard
Implementation
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
queryParams: {
access_type: 'offline',
prompt: 'consent',
},
},
})
GitHub OAuth
Setup GitHub OAuth
- Go to GitHub Developer Settings
- Click “New OAuth App”
- Fill in application details
- Authorization callback URL:
https://<project-ref>.supabase.co/auth/v1/callback
- Copy Client ID and Secret to Supabase dashboard
Implementation
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'github',
options: {
scopes: 'repo gist notifications',
},
})
Apple OAuth
Setup Apple Sign In
- Go to Apple Developer Portal
- Create a new identifier for Sign in with Apple
- Configure Services ID
- Add return URL:
https://<project-ref>.supabase.co/auth/v1/callback
- Copy Service ID and Key to Supabase dashboard
Implementation
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'apple',
})
Request Additional Scopes
Request extra permissions from OAuth providers:
// GitHub - request repo access
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'github',
options: {
scopes: 'repo user:email',
},
})
// Google - request calendar access
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
scopes: 'https://www.googleapis.com/auth/calendar',
},
})
// Discord - request guilds
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'discord',
options: {
scopes: 'identify email guilds',
},
})
Handle OAuth Callback
Next.js App Router
app/auth/callback/route.ts
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'
export async function GET(request: Request) {
const requestUrl = new URL(request.url)
const code = requestUrl.searchParams.get('code')
if (code) {
const cookieStore = cookies()
const supabase = createRouteHandlerClient({ cookies: () => cookieStore })
await supabase.auth.exchangeCodeForSession(code)
}
// URL to redirect to after sign in process completes
return NextResponse.redirect(new URL('/dashboard', request.url))
}
SvelteKit
routes/auth/callback/+server.ts
import { redirect } from '@sveltejs/kit'
import type { RequestHandler } from './$types'
export const GET: RequestHandler = async ({ url, locals: { supabase } }) => {
const code = url.searchParams.get('code')
if (code) {
await supabase.auth.exchangeCodeForSession(code)
}
throw redirect(303, '/dashboard')
}
Access Provider Tokens
Access the OAuth provider’s access token to call their APIs:
const { data: { session } } = await supabase.auth.getSession()
if (session?.provider_token) {
// Use the provider token to call their API
const response = await fetch('https://api.github.com/user/repos', {
headers: {
Authorization: `Bearer ${session.provider_token}`,
},
})
const repos = await response.json()
console.log('User repos:', repos)
}
Provider tokens are only available for certain providers and must be requested with the appropriate scopes.
Link OAuth Accounts
Link multiple OAuth providers to the same user:
// User is already signed in
const { data, error } = await supabase.auth.linkIdentity({
provider: 'google',
})
if (!error) {
console.log('Google account linked successfully')
}
Unlink OAuth Accounts
const { data, error } = await supabase.auth.unlinkIdentity({
identity_id: 'identity-uuid',
})
Server-Side OAuth
For server-side OAuth flows, use PKCE (Proof Key for Code Exchange):
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: 'http://localhost:3000/auth/callback',
skipBrowserRedirect: false,
},
})
// Redirect user to data.url
window.location.href = data.url
Mobile Deep Links
Configure deep links for mobile OAuth:
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: 'myapp://auth/callback',
skipBrowserRedirect: true,
},
})
Configure deep linking:
Add to Info.plist:<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>
Add to AndroidManifest.xml:<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp" />
</intent-filter>
Error Handling
Common OAuth errors:
| Error | Description | Solution |
|---|
provider_email_needs_verification | Email not verified | Ask user to verify email with provider |
provider_disabled | Provider not enabled | Enable in dashboard |
invalid_credentials | Wrong client ID/secret | Check provider credentials |
redirect_uri_mismatch | Wrong callback URL | Update provider settings |
Security Considerations
Always validate OAuth tokens on the server side before granting access to sensitive resources.
Use HTTPS
Always use HTTPS in production for OAuth callbacks
Validate State
Supabase automatically validates PKCE state parameters
Rotate Secrets
Regularly rotate OAuth client secrets
Minimal Scopes
Only request the scopes you actually need
Next Steps
Multi-Factor Auth
Add MFA for enhanced security
Row Level Security
Control data access with RLS