Documentation Index
Fetch the complete documentation index at: https://mintlify.com/flet-dev/flet/llms.txt
Use this file to discover all available pages before exploring further.
Flet provides a comprehensive authentication system with built-in OAuth support for popular identity providers. You can implement secure login flows with minimal code.
Overview
Flet’s authentication system consists of:
- OAuth Providers - Pre-configured providers (Google, GitHub, Azure, Auth0) and base classes for custom providers
- Authorization Service - Handles OAuth flows, token management, and automatic refresh
- Page.login() - Built-in page method to trigger authentication
- User & Token APIs - Access user profile and token data
Location: flet/auth/__init__.py:1
Quick Start
Here’s a minimal OAuth authentication example:
import flet as ft
from flet.auth import GoogleOAuthProvider
def main(page: ft.Page):
provider = GoogleOAuthProvider(
client_id="YOUR_CLIENT_ID.apps.googleusercontent.com",
client_secret="YOUR_CLIENT_SECRET",
redirect_url="http://localhost:8550/oauth_callback",
)
def login_click(e):
page.login(provider)
def on_login(e):
if e.error:
print(f"Login error: {e.error_description}")
else:
print(f"Logged in as: {page.auth.user.name}")
page.add(ft.Text(f"Welcome, {page.auth.user.name}!"))
page.on_login = on_login
page.add(
ft.ElevatedButton("Login with Google", on_click=login_click)
)
ft.run(main)
OAuth Providers
Flet includes providers for major identity platforms:
Google OAuth
from flet.auth import GoogleOAuthProvider
provider = GoogleOAuthProvider(
client_id="YOUR_CLIENT_ID.apps.googleusercontent.com",
client_secret="YOUR_CLIENT_SECRET",
redirect_url="http://localhost:8550/oauth_callback",
)
Setup:
- Go to Google Cloud Console
- Create a new project or select existing
- Enable Google+ API
- Create OAuth 2.0 credentials
- Add authorized redirect URI:
http://localhost:8550/oauth_callback
GitHub OAuth
from flet.auth import GitHubOAuthProvider
provider = GitHubOAuthProvider(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
redirect_url="http://localhost:8550/oauth_callback",
)
Setup:
- Go to GitHub Settings → Developer settings → OAuth Apps
- Create a new OAuth App
- Set Authorization callback URL:
http://localhost:8550/oauth_callback
Azure AD OAuth
from flet.auth import AzureOAuthProvider
provider = AzureOAuthProvider(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
redirect_url="http://localhost:8550/oauth_callback",
tenant="common", # or your tenant ID
)
Auth0 OAuth
from flet.auth import Auth0OAuthProvider
provider = Auth0OAuthProvider(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
redirect_url="http://localhost:8550/oauth_callback",
domain="your-domain.auth0.com",
)
Authorization Service
The AuthorizationService manages the complete OAuth flow:
Location: flet/auth/authorization_service.py:19
from flet.auth import AuthorizationService, GoogleOAuthProvider
provider = GoogleOAuthProvider(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
redirect_url="http://localhost:8550/oauth_callback",
)
auth_service = AuthorizationService(
provider=provider,
fetch_user=True, # Retrieve user profile
fetch_groups=False, # Retrieve user groups (if supported)
scope=["openid", "email", "profile"],
)
Authorization Flow
Location: flet/auth/authorization_service.py:90
- Get authorization URL:
auth_url, state = auth_service.get_authorization_data()
# Redirect user to auth_url
- Exchange code for token:
Location: flet/auth/authorization_service.py:111
# After redirect callback with authorization code
await auth_service.request_token(code)
- Access token:
Location: flet/auth/authorization_service.py:78
token = await auth_service.get_token()
print(token.access_token)
Token Persistence
Save and restore tokens for persistent sessions:
Location: flet/auth/authorization_service.py:62
# Save token
token = await auth_service.get_token()
token_json = token.to_json()
# Store token_json in secure storage
# Restore token
await auth_service.dehydrate_token(token_json)
Automatic Token Refresh
Tokens are automatically refreshed when expired:
Location: flet/auth/authorization_service.py:188
# This automatically refreshes if needed
token = await auth_service.get_token()
User Profile
Access authenticated user information:
def on_login(e):
if page.auth and page.auth.user:
user = page.auth.user
print(f"User ID: {user.id}")
print(f"Name: {user.name}")
print(f"Email: {user.email}")
print(f"Picture: {user.picture}")
# Raw user data from provider
print(f"Raw data: {user.data}")
OAuth Token
Access token details:
async def get_token_info(page):
if page.auth:
token = await page.auth.get_token()
print(f"Access Token: {token.access_token}")
print(f"Token Type: {token.token_type}")
print(f"Expires At: {token.expires_at}")
print(f"Refresh Token: {token.refresh_token}")
print(f"Scopes: {token.scope}")
Custom OAuth Provider
Create a custom provider by extending OAuthProvider:
Location: flet/auth/oauth_provider.py:7
from flet.auth import OAuthProvider, User, Group
class CustomOAuthProvider(OAuthProvider):
def __init__(self, client_id: str, client_secret: str, redirect_url: str):
super().__init__(
client_id=client_id,
client_secret=client_secret,
authorization_endpoint="https://example.com/oauth/authorize",
token_endpoint="https://example.com/oauth/token",
redirect_url=redirect_url,
scopes=["openid", "profile", "email"],
user_endpoint="https://example.com/api/user",
user_id_fn=lambda data: data["sub"],
)
def _name(self):
return "custom"
async def _fetch_user(self, access_token: str):
# Custom user fetching logic
async with httpx.AsyncClient() as client:
resp = await client.get(
"https://example.com/api/user",
headers={"Authorization": f"Bearer {access_token}"}
)
data = resp.json()
return User(data, str(data["id"]))
async def _fetch_groups(self, access_token: str) -> list[Group]:
# Custom group fetching logic
async with httpx.AsyncClient() as client:
resp = await client.get(
"https://example.com/api/groups",
headers={"Authorization": f"Bearer {access_token}"}
)
groups_data = resp.json()
return [Group(g["id"], g["name"]) for g in groups_data]
PKCE Support
For public clients, use PKCE (Proof Key for Code Exchange):
import secrets
import hashlib
import base64
def generate_pkce():
code_verifier = base64.urlsafe_b64encode(secrets.token_bytes(32)).decode('utf-8').rstrip('=')
code_challenge = base64.urlsafe_b64encode(
hashlib.sha256(code_verifier.encode('utf-8')).digest()
).decode('utf-8').rstrip('=')
return code_verifier, code_challenge
code_verifier, code_challenge = generate_pkce()
provider = GoogleOAuthProvider(
client_id="YOUR_CLIENT_ID",
client_secret="", # Not needed for PKCE
redirect_url="http://localhost:8550/oauth_callback",
code_challenge=code_challenge,
code_challenge_method="S256",
code_verifier=code_verifier,
)
Authentication with Components
Combine authentication with component-based architecture:
import flet as ft
from flet.auth import GoogleOAuthProvider
# Create context for auth state
AuthContext = ft.create_context(default_value=None)
@ft.component
def ProtectedRoute():
auth = ft.use_context(AuthContext)
if not auth:
return ft.Text("Please log in to view this content")
return ft.Column([
ft.Text(f"Welcome, {auth.user.name}!"),
ft.Text(f"Email: {auth.user.email}"),
])
@ft.component
def App():
auth_state, set_auth_state = ft.use_state(None)
provider = GoogleOAuthProvider(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
redirect_url="http://localhost:8550/oauth_callback",
)
def login(_):
ft.context.page.login(provider)
def on_login(e):
if not e.error:
set_auth_state(ft.context.page.auth)
ft.use_effect(
lambda: setattr(ft.context.page, 'on_login', on_login),
dependencies=[]
)
return AuthContext(
auth_state,
lambda: ft.Column([
ft.ElevatedButton("Login", on_click=login) if not auth_state else ft.Container(),
ProtectedRoute(),
])
)
ft.run(lambda page: page.render(App))
Token Storage Best Practices
- Never store tokens in plain text - Use secure storage mechanisms
- Encrypt tokens at rest - Use platform-specific secure storage
- Use short-lived tokens - Rely on refresh tokens for long sessions
- Implement logout - Clear stored tokens on logout
import keyring
# Store token securely
token = await auth_service.get_token()
keyring.set_password("myapp", "oauth_token", token.to_json())
# Retrieve token
token_json = keyring.get_password("myapp", "oauth_token")
if token_json:
await auth_service.dehydrate_token(token_json)
# Clear token on logout
keyring.delete_password("myapp", "oauth_token")
Error Handling
def on_login(e):
if e.error:
error_messages = {
"access_denied": "User denied access",
"invalid_request": "Invalid authentication request",
"server_error": "Authentication server error",
}
message = error_messages.get(
e.error,
f"Login failed: {e.error_description}"
)
page.show_snack_bar(
ft.SnackBar(content=ft.Text(message, color=ft.Colors.WHITE))
)
else:
print("Login successful!")
Complete Example: Multi-Provider Auth
import flet as ft
from flet.auth import GoogleOAuthProvider, GitHubOAuthProvider
def main(page: ft.Page):
page.title = "Multi-Provider Auth"
providers = {
"google": GoogleOAuthProvider(
client_id="GOOGLE_CLIENT_ID",
client_secret="GOOGLE_CLIENT_SECRET",
redirect_url="http://localhost:8550/oauth_callback",
),
"github": GitHubOAuthProvider(
client_id="GITHUB_CLIENT_ID",
client_secret="GITHUB_CLIENT_SECRET",
redirect_url="http://localhost:8550/oauth_callback",
),
}
def login_with_provider(provider_name):
def on_click(e):
page.login(providers[provider_name])
return on_click
def on_login(e):
if e.error:
page.add(ft.Text(f"Error: {e.error_description}", color=ft.Colors.RED))
else:
page.clean()
page.add(
ft.Column([
ft.Text(f"Welcome, {page.auth.user.name}!", size=24),
ft.Text(f"Email: {page.auth.user.email}"),
ft.ElevatedButton("Logout", on_click=logout),
])
)
def logout(e):
page.logout()
page.clean()
show_login_screen()
def show_login_screen():
page.add(
ft.Column([
ft.Text("Login with:", size=20),
ft.ElevatedButton(
"Google",
icon=ft.Icons.ACCOUNT_CIRCLE,
on_click=login_with_provider("google")
),
ft.ElevatedButton(
"GitHub",
icon=ft.Icons.CODE,
on_click=login_with_provider("github")
),
], spacing=10)
)
page.on_login = on_login
show_login_screen()
ft.run(main)
Security Considerations
- Use HTTPS in production - Never use OAuth over HTTP
- Validate redirect URLs - Ensure redirect URLs match registered callbacks
- Implement CSRF protection - Validate the
state parameter
- Rotate client secrets - Regularly update OAuth credentials
- Limit token scope - Request only necessary permissions
- Implement token revocation - Provide logout functionality
- Monitor for suspicious activity - Log authentication events
Next Steps