Flaxon OAuth Google
Google OAuth 2.0 authentication plugin for Flaxon framework.
Table of Contents
Features
- 🔐 OAuth 2.0 Authorization Code Flow — Full OAuth 2.0 implementation
- 👤 User Info Retrieval — Fetch user profile from Google's API
- 🔄 Session Management — Optional session creation after authentication
- 🛡️ CSRF Protection — State parameter validation
- ⚙️ Configurable Scopes — Request only the permissions you need
- 🧩 User Mapping — Map Google user data to your app's user model
- 🎯 Error Handling — Graceful OAuth error handling
- 🔁 Refresh Tokens — Automatic token refresh support
Installation
pip install flaxon-oauth-google
Quick Start
from flaxon import Flaxon
from flaxon_oauth_google import GoogleOAuthPlugin
app = Flaxon("my-app")
# Basic usage with environment variables
app.plugins.load_plugin(GoogleOAuthPlugin(
client_id="your-client-id.apps.googleusercontent.com",
client_secret="your-client-secret",
redirect_uri="https://yourapp.com/auth/google/callback",
))
@app.get("/")
async def home(request):
return """
<a href="/auth/google/login">Sign in with Google</a>
"""
Configuration
Environment Variables
# Required
export GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
export GOOGLE_CLIENT_SECRET=your-client-secret
# Optional
export GOOGLE_REDIRECT_URI=https://yourapp.com/auth/google/callback
export GOOGLE_SCOPES=openid,email,profile
export GOOGLE_SUCCESS_REDIRECT=/dashboard
export GOOGLE_FAILURE_REDIRECT=/login?error=oauth_failed
With Flaxon Config
app = Flaxon("my-app", config={
"GOOGLE_CLIENT_ID": "your-client-id",
"GOOGLE_CLIENT_SECRET": "your-client-secret",
"GOOGLE_REDIRECT_URI": "https://yourapp.com/auth/google/callback",
})
plugin = GoogleOAuthPlugin.from_config(app.config)
app.plugins.load_plugin(plugin)
Advanced Usage
Custom Session Creation
def create_session_from_user(google_user):
"""Create a session from Google user data."""
user = app_user_from_google(google_user)
session_token = generate_session_token(user)
return session_token
plugin = GoogleOAuthPlugin(
client_id="...",
client_secret="...",
redirect_uri="...",
session_maker=create_session_from_user,
success_redirect="/dashboard",
)
app.plugins.load_plugin(plugin)
Custom User Mapping
def map_google_user(google_user):
"""Map Google user to app user model."""
return {
"external_id": google_user.id,
"email": google_user.email,
"email_verified": google_user.verified_email,
"full_name": google_user.name,
"first_name": google_user.given_name,
"last_name": google_user.family_name,
"avatar_url": google_user.picture,
"locale": google_user.locale,
}
plugin = GoogleOAuthPlugin(
client_id="...",
client_secret="...",
redirect_uri="...",
user_mapper=map_google_user,
)
Custom Scopes
# Request only what you need
plugin = GoogleOAuthPlugin(
client_id="...",
client_secret="...",
redirect_uri="...",
scopes=["openid", "email"], # Just email, no profile
)
# Or request additional scopes
plugin = GoogleOAuthPlugin(
client_id="...",
client_secret="...",
redirect_uri="...",
scopes=[
"openid",
"email",
"profile",
"https://www.googleapis.com/auth/drive.readonly"
],
)
Protected Routes
from flaxon_oauth_google import login_required
@app.get("/profile")
@login_required
async def profile(request):
user = request.session.get("user")
return {
"name": user.get("name"),
"email": user.get("email"),
"picture": user.get("picture"),
}
@app.get("/settings")
@login_required
async def settings(request):
return {"settings": "..."}
OAuth Endpoints
| Route | Method | Description |
|---|---|---|
/auth/google/login |
GET | Redirect to Google consent screen |
/auth/google/callback |
GET | OAuth callback endpoint |
/auth/google/logout |
GET | Clear session (optional) |
/auth/google/user |
GET | Get current user info |
Security Best Practices
✅ Store client secret in environment variables
✅ Use HTTPS in production
✅ Validate redirect URI matches registered URI
✅ Use state parameter for CSRF protection
✅ Verify ID token signature
✅ Keep scopes minimal (least privilege)
✅ Regenerate session ID on login
✅ Use secure cookies (Secure, HttpOnly, SameSite)
Example Application
Complete Setup
from flaxon import Flaxon
from flaxon_oauth_google import GoogleOAuthPlugin
import os
app = Flaxon("my-app")
# Load plugin
plugin = GoogleOAuthPlugin(
client_id=os.environ["GOOGLE_CLIENT_ID"],
client_secret=os.environ["GOOGLE_CLIENT_SECRET"],
redirect_uri=f"{os.environ['APP_URL']}/auth/google/callback",
scopes=["openid", "email", "profile"],
success_redirect="/dashboard",
failure_redirect="/login?error=oauth_failed",
)
def create_session(google_user):
"""Create a session for the user."""
# Your session creation logic
session_id = f"session_{google_user.id}_{int(time.time())}"
return session_id
plugin.session_maker = create_session
app.plugins.load_plugin(plugin)
@app.get("/")
async def home(request):
return """
<html>
<body>
<h1>Welcome to My App</h1>
<a href="/auth/google/login">
<button>Sign in with Google</button>
</a>
</body>
</html>
"""
@app.get("/dashboard")
async def dashboard(request):
user = request.session.get("user")
if not user:
return {"error": "Not authenticated"}, 401
return {
"welcome": f"Hello, {user.get('name')}!",
"email": user.get("email"),
"picture": user.get("picture"),
}
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)
Testing
# Run tests
pytest
# Run with coverage
pytest --cov=flaxon_oauth_google
# Run specific test
pytest tests/test_provider.py -v
Requirements
Python 3.11+
Flaxon 0.1.0+
httpx 0.27.0+
pyjwt 2.8.0+
cryptography 42.0.0+
Project Structure
flaxon-oauth-google/
├── pyproject.toml
├── README.md
├── LICENSE
├── src/
│ └── flaxon_oauth_google/
│ ├── __init__.py # Public API exports
│ ├── plugin.py # GoogleOAuthPlugin class
│ ├── provider.py # GoogleOAuthProvider
│ ├── client.py # Google API client
│ ├── user.py # User info mapping
│ └── routes.py # OAuth route handlers
└── tests/
├── test_plugin.py
├── test_provider.py
└── test_integration.py
Roadmap
| Version | Features |
|---|---|
| 0.1.0 | Basic Google OAuth flow |
| 0.2.0 | G Suite domain restriction |
| 0.3.0 | Service account support |
| 0.4.0 | Social login buttons (HTML helpers) |
| 0.5.0 | Refresh token rotation |
Contributing
Fork the repository
Create a feature branch
Add tests for new features
Ensure all tests pass
Submit a pull request
License
MIT License - See LICENSE file for details.
Support
📚 Documentation
🐛 Issue Tracker
💬 Discussions
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flaxon_oauth_google-0.1.2.tar.gz.
File metadata
- Download URL: flaxon_oauth_google-0.1.2.tar.gz
- Upload date:
- Size: 18.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2d3861aa995f8d13f1dea17e57230729600c4ff236cbe0c7896ffadba49e8285
|
|
| MD5 |
002b9651ebf72fa1ef8631143636edff
|
|
| BLAKE2b-256 |
487212239e250af614aff5181303673707d081111c573f8e4d59fd6ebeee50b2
|
File details
Details for the file flaxon_oauth_google-0.1.2-py3-none-any.whl.
File metadata
- Download URL: flaxon_oauth_google-0.1.2-py3-none-any.whl
- Upload date:
- Size: 13.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0ce146649871bbb1fe0f9acb621d7b0f489c8103f2ee0f3b16ce8989c4b484b7
|
|
| MD5 |
4f02e76b35cf315ee20b969c2ea72d1c
|
|
| BLAKE2b-256 |
27d5bd4fc2db9bd1ed856a815579db560e4558e59ac7c5e344b0a4acd390f0df
|