To enable SSO authentication using Keycloak and LDAP in your FastAPI application, you need to integrate OAuth 2.0 / OpenID Connect (OIDC) authentication using Keycloak as the identity provider. Here’s a step-by-step guide:
1. How It Works
- Users attempt to access FastAPI
- FastAPI redirects users to Keycloak for authentication
- Keycloak authenticates users via LDAP
- Keycloak returns an OAuth 2.0 token to the FastAPI application
- FastAPI validates the token and grants access
2. Prerequisites
- A FastAPI application
- A running Keycloak server with LDAP federation configured (Follow the existing blog)
- Keycloak realm and client set up for OAuth 2.0 authentication
- Python 3.7+ and
fastapi
,httpx
, andpyjwt
installed
3. Configure Keycloak for FastAPI OAuth 2.0
Step 1: Create a Keycloak Client
- Log in to Keycloak Admin Console:
👉http://localhost:8080/admin
- Select your realm (or create one)
- Navigate to Clients → Click Create
- Set the following:
- Client ID:
fastapi-client
- Client Protocol:
openid-connect
- Root URL:
http://localhost:8000
- Access Type:
Confidential
- Client ID:
- Click Save
Step 2: Configure Credentials
- Go to Clients → fastapi-client → Credentials
- Copy the Client Secret for later use
Step 3: Add Redirect URI
- Under the FastAPI client → Settings section:
- Set Valid Redirect URIs to
http://localhost:8000/login
- Click Save
- Set Valid Redirect URIs to
4. Implement SSO in FastAPI
Install Required Packages
pip install fastapi uvicorn python-dotenv httpx pyjwt
Create FastAPI Application
1️⃣ Define Configuration
Create a .env
file:
KEYCLOAK_SERVER_URL=http://localhost:8080
KEYCLOAK_REALM=myrealm
KEYCLOAK_CLIENT_ID=fastapi-client
KEYCLOAK_CLIENT_SECRET=<your_client_secret>
REDIRECT_URI=http://localhost:8000/login
2️⃣ FastAPI Code for SSO Authentication
Create main.py
:
import os
import httpx
import jwt
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2AuthorizationCodeBearer
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Keycloak config
KEYCLOAK_URL = os.getenv("KEYCLOAK_SERVER_URL")
REALM = os.getenv("KEYCLOAK_REALM")
CLIENT_ID = os.getenv("KEYCLOAK_CLIENT_ID")
CLIENT_SECRET = os.getenv("KEYCLOAK_CLIENT_SECRET")
REDIRECT_URI = os.getenv("REDIRECT_URI")
# OAuth 2.0 flow
oauth2_scheme = OAuth2AuthorizationCodeBearer(
tokenUrl=f"{KEYCLOAK_URL}/realms/{REALM}/protocol/openid-connect/token",
authorizationUrl=f"{KEYCLOAK_URL}/realms/{REALM}/protocol/openid-connect/auth"
)
app = FastAPI()
# Step 1: Redirect to Keycloak Login
@app.get("/auth")
async def login():
auth_url = (
f"{KEYCLOAK_URL}/realms/{REALM}/protocol/openid-connect/auth?"
f"client_id={CLIENT_ID}&response_type=code&"
f"scope=openid&redirect_uri={REDIRECT_URI}"
)
return {"login_url": auth_url}
# Step 2: Handle Callback and Exchange Code for Token
@app.get("/login")
async def callback(code: str):
token_url = f"{KEYCLOAK_URL}/realms/{REALM}/protocol/openid-connect/token"
data = {
"grant_type": "authorization_code",
"code": code,
"redirect_uri": REDIRECT_URI,
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
}
async with httpx.AsyncClient() as client:
response = await client.post(token_url, data=data)
token_response = response.json()
if "access_token" not in token_response:
raise HTTPException(status_code=400, detail="Failed to authenticate")
return {"access_token": token_response["access_token"]}
# Step 3: Protect Routes with Token Verification
def get_current_user(token: str = Depends(oauth2_scheme)):
try:
payload = jwt.decode(token, options={"verify_signature": False})
return {"username": payload["preferred_username"]}
except jwt.PyJWTError:
raise HTTPException(status_code=401, detail="Invalid token")
@app.get("/protected")
async def protected_route(user: dict = Depends(get_current_user)):
return {"message": "You have accessed a protected route!", "user": user}
5. Running the FastAPI Server
uvicorn main:app --reload --port 8000
6. Testing SSO Authentication
- Visit
http://localhost:8000/auth
in your browser - Redirects to Keycloak login
- Login with an LDAP user
- Keycloak redirects back to FastAPI with an authorization code
- FastAPI exchanges the code for an access token
- Use the access token to access protected routes:
curl -H "Authorization: Bearer <ACCESS_TOKEN>" http://localhost:8000/protected
Conclusion
You’ve successfully implemented SSO authentication in FastAPI using Keycloak and LDAP. Now, users can log in via Keycloak, which authenticates them against LDAP.
Next Steps
✅ Implement Role-Based Access Control (RBAC)
✅ Secure APIs with OAuth 2.0 scopes
✅ Deploy Keycloak & FastAPI on Docker/Kubernetes