By Chirag Patil · · 4 min read
How to Add Supabase OAuth to FastAPI
A comprehensive guide on integrating Supabase OAuth with FastAPI for secure social logins using GitHub, Google, and other providers.
How to add Supabase OAuth in FastAPI
In this post, we'll walk through how to quickly add secure social logins (like Google, GitHub, etc.) to your FastAPI application using Supabase OAuth.
We'll use my pre-built template to get you started in minutes.
Check out the complete code template on GitHub:
https://github.com/QueryPlanner/FastAPI-Supabase-Auth-Template.git
The Core Concepts (In a Nutshell)
- FastAPI: Our high-performance Python web framework for building the API.
- Supabase: Our Backend-as-a-Service. It will act as a trusted middleman, handling the complex OAuth flow with providers like Google or GitHub so we don't have to.
- OAuth Flow: The user journey is simple:
- User clicks "Login with GitHub" on your app.
- Your FastAPI app asks Supabase for a special login URL and sends the user there.
- User approves the login on GitHub.
- GitHub sends the user back to your FastAPI app with a temporary "code".
- Your app exchanges this code with Supabase for a real user session token (JWT).
- The user is now logged in!
Step 1: Clone the Template Repository
Let's start by cloning the FastAPI + Supabase template, which contains all the boilerplate code we need.
git clone https://github.com/QueryPlanner/FastAPI-Supabase-Auth-Template.git
cd FastAPI-Supabase-Auth-Template
Next, install the required Python packages.
pip install -r requirements.txt
Step 2: Configure Your Supabase Project
-
Create a Supabase Project: If you don't have one, go to supabase.com and create a new project.
-
Enable an OAuth Provider:
- In your Supabase project, navigate to Authentication -> Providers.
- Choose a provider you want to enable (e.g., GitHub).
- You'll see a Redirect URL (also called a Callback URL). Copy this URL. You'll need it in a moment.
- Now, go to your provider's developer settings (e.g., GitHub's OAuth Apps page) and create a new OAuth App.
- Paste the Redirect URL you copied from Supabase into the "Authorization callback URL" field on the provider's site.
- The provider will give you a Client ID and a Client Secret. Copy these back into the matching fields in your Supabase provider settings.
- Click Save.
Step 3: Configure Your FastAPI Application
The template uses a .env file to manage secret keys. Rename the example.env file to .env and fill it with your Supabase credentials.
# .env
# Find these in your Supabase Project -> Settings -> API
SUPABASE_PROJECT_URL="https://your-project-ref.supabase.co"
SUPABASE_API_KEY="your-public-anon-key"
# Find this in your Supabase Project -> Settings -> API -> JWT Settings
SUPABASE_JWT_SECRET="your-jwt-secret-from-supabase-settings"
Step 4: The Code That Makes It Happen
The magic happens in just two API endpoints in main.py. Let's replace the existing email/password routes with our new OAuth routes.
# main.py
from fastapi import FastAPI, Depends, HTTPException, Request, Query
from fastapi.responses import RedirectResponse
from gotrue.errors import AuthApiError
# Import our custom modules
from supabase_client import supabase
from schemas import AuthResponse
from auth import JWTBearer
app = FastAPI(
title="FastAPI Supabase OAuth",
description="A demo of Supabase OAuth with FastAPI.",
version="1.0.0",
)
# Dependency for our protected routes
auth_dependency = Depends(JWTBearer())
@app.get("/login/{provider}", response_class=RedirectResponse, tags=["Auth"])
async def oauth_login(provider: str):
"""
Generates the OAuth login URL for the given provider and redirects the user.
"""
# The redirect_to URL should point back to your backend's callback endpoint.
# In a real app, this might be a frontend URL.
url, _ = supabase.auth.sign_in_with_oauth({
"provider": provider,
"options": {
"redirect_to": "http://127.0.0.1:8000/callback"
}
})
return RedirectResponse(url)
@app.get("/callback", response_model=AuthResponse, tags=["Auth"])
async def callback(request: Request, code: str = Query(...)):
"""
Handles the callback from the OAuth provider.
Exchanges the authorization code for a user session (JWT).
"""
try:
# Exchange the code for a valid session
session_data = supabase.auth.exchange_code_for_session({"auth_code": code})
# Return the session details to the user
return {
"access_token": session_data.session.access_token,
"refresh_token": session_data.session.refresh_token,
"user": {
"id": session_data.user.id,
"email": session_data.user.email
}
}
except AuthApiError as e:
raise HTTPException(
status_code=400,
detail=f"Invalid code or failed OAuth exchange: {e.message}"
)
@app.get("/me", dependencies=[auth_dependency], tags=["Protected"])
async def protected_route(payload: dict = auth_dependency):
"""
A protected route that only authenticated users can access.
The user's JWT payload is injected by the JWTBearer dependency.
"""
user_id = payload.get("sub")
return {"message": f"Hello from a protected route! Your User ID is: {user_id}"}
How it works:
/login/{provider}: This endpoint simply asks Supabase to create a unique login URL for the provider (likegithuborgoogle) and immediately redirects the user's browser to that URL./callback: This is where the provider sends the user back after they've approved the login. The URL will contain a temporarycode. Our code grabs thiscodeand usessupabase.auth.exchange_code_for_sessionto trade it for a permanentaccess_token. This token is the key to proving the user is logged in./me: This is a protected route. Theauth.pyfile in the template contains aJWTBearerclass that acts as a bouncer. It checks for a validaccess_tokenin the request header before allowing access.
Step 5: Run and Test Your OAuth Flow
-
Start the server:
uvicorn main:app --reload -
Initiate Login: Open your web browser and go to the login URL for the provider you configured (e.g., GitHub):
http://127.0.0.1:8000/login/github -
Authorize: You will be sent to GitHub to authorize the application. Click "Authorize".
-
Get Your Token: GitHub will redirect you back to
http://127.0.0.1:8000/callback, and you'll see a JSON response in your browser containing youraccess_token. Copy it! -
Test the Protected Route:
- Navigate to the API docs at
http://127.0.0.1:8000/docs. - Click the Authorize button at the top right.
- In the popup, type
Bearer <your_access_token>and click Authorize. - Now, try out the
/meendpoint. It will work!
- Navigate to the API docs at
Conclusion
That's it! You've successfully integrated a secure, third-party social login into your FastAPI application. By letting Supabase handle the OAuth complexity, you can focus on building your app's core features while providing a seamless login experience for your users.
Feel free to extend the template and add more providers! Happy coding.
Author: Chirag Patil