Skip to main content

Flaxon OAuth Google

Flaxon Logo

PyPI version License: MIT Code style: ruff

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

flaxon_oauth_google-0.1.2.tar.gz (18.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flaxon_oauth_google-0.1.2-py3-none-any.whl (13.9 kB view details)

Uploaded Python 3

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

Hashes for flaxon_oauth_google-0.1.2.tar.gz
Algorithm Hash digest
SHA256 2d3861aa995f8d13f1dea17e57230729600c4ff236cbe0c7896ffadba49e8285
MD5 002b9651ebf72fa1ef8631143636edff
BLAKE2b-256 487212239e250af614aff5181303673707d081111c573f8e4d59fd6ebeee50b2

See more details on using hashes here.

File details

Details for the file flaxon_oauth_google-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for flaxon_oauth_google-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 0ce146649871bbb1fe0f9acb621d7b0f489c8103f2ee0f3b16ce8989c4b484b7
MD5 4f02e76b35cf315ee20b969c2ea72d1c
BLAKE2b-256 27d5bd4fc2db9bd1ed856a815579db560e4558e59ac7c5e344b0a4acd390f0df

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page