Python SDK
Official OAuth42 SDK for Python. Works with Django, Flask, FastAPI, and any Python web framework.
Installation
Install the OAuth42 SDK using pip:
pip install oauth42Requirements
Python 3.8 or higher. The SDK uses modern Python features including type hints for better IDE support.
Quick Start
1. Initialize the Client
from oauth42 import OAuth42Client
client = OAuth42Client(
client_id="your_client_id",
client_secret="your_client_secret", # Optional for server-side
redirect_uri="https://yourapp.com/callback",
issuer="https://oauth42.com", # Optional
)2. Start Authorization Flow
# Generate authorization URL with PKCE
auth_data = client.authorize(
scope=["openid", "profile", "email"],
response_type="code"
)
# Store code_verifier and state in session
session['code_verifier'] = auth_data['code_verifier']
session['state'] = auth_data['state']
# Redirect user to authorization URL
return redirect(auth_data['url'])3. Handle Callback
# Parse callback parameters
code = request.args.get('code')
state = request.args.get('state')
# Verify state
if state != session.get('state'):
raise ValueError("Invalid state parameter")
# Exchange code for tokens
tokens = client.exchange_code_for_tokens(
code=code,
code_verifier=session.get('code_verifier')
)
# Access tokens
print(f"Access token: {tokens['access_token']}")
print(f"Refresh token: {tokens['refresh_token']}")
print(f"ID token: {tokens['id_token']}")Configuration
The OAuth42Client class accepts the following parameters:
client_idrequiredYour application's client ID from the OAuth42 dashboard.
redirect_urirequiredThe redirect URI registered in your OAuth42 application settings.
client_secretoptionalYour application's client secret. Required for confidential clients.
issueroptionalThe OAuth42 issuer URL. Defaults to https://oauth42.com
timeoutoptionalRequest timeout in seconds. Defaults to 30
Authentication Flows
Authorization Code Flow with PKCE
from oauth42 import OAuth42Client
client = OAuth42Client(
client_id=os.getenv("OAUTH42_CLIENT_ID"),
client_secret=os.getenv("OAUTH42_CLIENT_SECRET"),
redirect_uri="http://localhost:5000/callback"
)
# Start authorization
auth_data = client.authorize(
scope=["openid", "profile", "email"],
response_type="code"
)
# Store in session
session['code_verifier'] = auth_data['code_verifier']
session['state'] = auth_data['state']
# Redirect
return redirect(auth_data['url'])
# --- After callback ---
# Exchange code for tokens
tokens = client.exchange_code_for_tokens(
code=request.args.get('code'),
code_verifier=session.get('code_verifier')
)Client Credentials Flow
# Server-to-server authentication
tokens = client.client_credentials(
scope=["api:read", "api:write"]
)
access_token = tokens['access_token']Refresh Token Flow
# Refresh expired access token
new_tokens = client.refresh_tokens(
refresh_token=stored_refresh_token
)
print(f"New access token: {new_tokens['access_token']}")
print(f"New refresh token: {new_tokens['refresh_token']}")User Management
Get User Info
user_info = client.get_user_info(access_token)
print(f"User ID: {user_info['sub']}")
print(f"Name: {user_info['name']}")
print(f"Email: {user_info['email']}")
print(f"Email verified: {user_info['email_verified']}")Update User Profile
client.update_user(
access_token,
name="John Doe",
picture="https://example.com/avatar.jpg"
)Change Password
client.change_password(
access_token,
current_password="old_password",
new_password="new_secure_password"
)Token Management
Validate Token
is_valid = client.validate_token(access_token)
if is_valid:
print("Token is valid")
else:
print("Token is expired or invalid")Introspect Token
token_info = client.introspect_token(access_token)
print(f"Active: {token_info['active']}")
print(f"Expires at: {token_info['exp']}")
print(f"Scopes: {token_info['scope']}")
print(f"Client ID: {token_info['client_id']}")Revoke Token
# Revoke access token or refresh token
client.revoke_token(token)
print("Token revoked successfully")Multi-Factor Authentication
Setup MFA
mfa_setup = client.setup_mfa(access_token)
print(f"Secret: {mfa_setup['secret']}")
print(f"QR Code: {mfa_setup['qr_code']}")
print(f"Backup codes: {mfa_setup['backup_codes']}")
# User scans QR code with authenticator app
# Then verify with first code
client.verify_mfa_setup(access_token, code="123456")Verify MFA Code
# During login, after receiving MFA challenge
tokens = client.verify_mfa(
mfa_token=mfa_token,
code="123456"
)
print(f"Access token: {tokens['access_token']}")Disable MFA
client.disable_mfa(
access_token,
password="user_password"
)Error Handling
The SDK raises typed exceptions that you can catch and handle:
from oauth42 import OAuth42Client, OAuth42Error
try:
tokens = client.exchange_code_for_tokens(
code=auth_code,
code_verifier=verifier
)
except OAuth42Error as error:
print(f"OAuth42 Error: {error.message}")
print(f"Error code: {error.code}")
print(f"Status: {error.status}")
if error.code == "invalid_grant":
# Authorization code expired or invalid
print("Authorization code is invalid")
elif error.code == "invalid_client":
# Client credentials are wrong
print("Client authentication failed")
elif error.code == "access_denied":
# User denied authorization
print("User denied access")
else:
print(f"Unknown error: {error.code}")
except Exception as error:
# Network or other error
print(f"Unexpected error: {error}")Common Error Codes
invalid_grantAuthorization code or refresh token is invalid or expired
invalid_clientClient authentication failed (wrong credentials)
invalid_requestRequest is missing required parameters or malformed
unauthorized_clientClient is not authorized for this grant type
Framework Integration
Flask
from flask import Flask, redirect, request, session, url_for
from oauth42 import OAuth42Client
import os
app = Flask(__name__)
app.secret_key = os.getenv("SECRET_KEY")
client = OAuth42Client(
client_id=os.getenv("OAUTH42_CLIENT_ID"),
client_secret=os.getenv("OAUTH42_CLIENT_SECRET"),
redirect_uri="http://localhost:5000/callback"
)
@app.route("/login")
def login():
auth_data = client.authorize(
scope=["openid", "profile", "email"]
)
session['code_verifier'] = auth_data['code_verifier']
session['state'] = auth_data['state']
return redirect(auth_data['url'])
@app.route("/callback")
def callback():
code = request.args.get('code')
state = request.args.get('state')
if state != session.get('state'):
return "Invalid state", 400
tokens = client.exchange_code_for_tokens(
code=code,
code_verifier=session.get('code_verifier')
)
session['access_token'] = tokens['access_token']
return redirect(url_for('dashboard'))
@app.route("/dashboard")
def dashboard():
if 'access_token' not in session:
return redirect(url_for('login'))
user = client.get_user_info(session['access_token'])
return f"Welcome, {user['name']}!"
if __name__ == "__main__":
app.run(debug=True)FastAPI
from fastapi import FastAPI, Request, Depends
from fastapi.responses import RedirectResponse
from oauth42 import OAuth42Client
import os
app = FastAPI()
client = OAuth42Client(
client_id=os.getenv("OAUTH42_CLIENT_ID"),
client_secret=os.getenv("OAUTH42_CLIENT_SECRET"),
redirect_uri="http://localhost:8000/callback"
)
@app.get("/login")
async def login(request: Request):
auth_data = client.authorize(
scope=["openid", "profile", "email"]
)
request.session['code_verifier'] = auth_data['code_verifier']
request.session['state'] = auth_data['state']
return RedirectResponse(auth_data['url'])
@app.get("/callback")
async def callback(request: Request, code: str, state: str):
if state != request.session.get('state'):
return {"error": "Invalid state"}
tokens = client.exchange_code_for_tokens(
code=code,
code_verifier=request.session.get('code_verifier')
)
request.session['access_token'] = tokens['access_token']
return RedirectResponse("/dashboard")
@app.get("/dashboard")
async def dashboard(request: Request):
access_token = request.session.get('access_token')
if not access_token:
return RedirectResponse("/login")
user = client.get_user_info(access_token)
return {"user": user}Django
# views.py
from django.shortcuts import redirect
from django.http import JsonResponse
from oauth42 import OAuth42Client
import os
client = OAuth42Client(
client_id=os.getenv("OAUTH42_CLIENT_ID"),
client_secret=os.getenv("OAUTH42_CLIENT_SECRET"),
redirect_uri="http://localhost:8000/callback"
)
def login(request):
auth_data = client.authorize(
scope=["openid", "profile", "email"]
)
request.session['code_verifier'] = auth_data['code_verifier']
request.session['state'] = auth_data['state']
return redirect(auth_data['url'])
def callback(request):
code = request.GET.get('code')
state = request.GET.get('state')
if state != request.session.get('state'):
return JsonResponse({"error": "Invalid state"}, status=400)
tokens = client.exchange_code_for_tokens(
code=code,
code_verifier=request.session.get('code_verifier')
)
request.session['access_token'] = tokens['access_token']
return redirect('/dashboard')
def dashboard(request):
access_token = request.session.get('access_token')
if not access_token:
return redirect('/login')
user = client.get_user_info(access_token)
return JsonResponse({"user": user})Best Practices
Use Environment Variables
Store sensitive credentials in environment variables, never hardcode them in source code.
Always Use PKCE
PKCE is enabled by default and provides additional security against authorization code interception attacks.
Implement Token Refresh
Automatically refresh access tokens before they expire to maintain seamless user sessions.
Validate State Parameter
Always verify the state parameter matches to prevent CSRF attacks during the OAuth flow.
Handle Errors Gracefully
Catch OAuth42Error exceptions and provide meaningful feedback to users while logging details for debugging.
Use Type Hints
The SDK includes full type hints. Use them with mypy or Pyright for better type safety and IDE support.
Next Steps
Build Your First App
Follow our step-by-step tutorial to integrate OAuth42 authentication.
API Reference
Complete OAuth42 API documentation with detailed endpoint specifications.
Multi-Factor Authentication
Implement TOTP-based MFA for enhanced account security.
Security Best Practices
Learn how to secure your OAuth 2.0 implementation.