Skip to main content

Add OAuth login to your FastAPI app in one command. 6 providers, PKCE support, and a built-in OAuth debugger.

Project description

OAuth for Dummies

The fastest way to add OAuth login to any FastAPI app. 6 providers, PKCE support, and a built-in OAuth debugger.

PyPI version Python 3.9+ FastAPI GitHub stars MIT License

Quickstart | Providers | OAuth Debugger | PKCE / OAuth 2.1 | How OAuth Works | CLI Reference | Tutorial


Why this exists

Adding OAuth to a FastAPI app should not take an afternoon. But it does, because:

  • The official OAuth 2.0 spec is 76 pages long
  • Every tutorial shows a different approach
  • Redirect URI mismatches waste hours of debugging
  • Production auth libraries are overkill when you just need "Login with GitHub"

oauth-for-dummies solves this. One CLI command drops working OAuth routes into your project. Two lines of code to integrate. Done.


Supported Providers

Provider Status Scopes
GitHub Ready read:user, user:email
Google Ready openid, email, profile
Discord Ready identify, email
Spotify Ready user-read-email, user-read-private
Microsoft Ready openid, email, profile, User.Read
LinkedIn Ready openid, profile, email

All 6 providers work with both the CLI scaffold (oauth-init) and the tutorial app. Only configure the ones you need -- unconfigured providers are hidden from the UI.


Quickstart

pip install oauth-for-dummies
cd your-fastapi-project
oauth-init

That scaffolds three files into your project:

your-fastapi-project/
  oauth_config.py       # provider credentials from .env (6 providers)
  oauth_routes.py       # login, callback, logout endpoints + PKCE support
  oauth_example_app.py  # working demo app (optional)
  .env                  # template for your OAuth keys

Integrate into your existing FastAPI app with two lines:

from oauth_routes import router as oauth_router

app.include_router(oauth_router)

Run the example to see it work:

pip install fastapi uvicorn httpx python-dotenv
# edit .env with your OAuth credentials
uvicorn oauth_example_app:app --reload
# open http://localhost:8000

OAuth Debugger

The tutorial app includes a built-in OAuth Debugger (Learn Mode) that captures and displays every HTTP request and response in the OAuth flow -- in real time, with real data.

Click Learn Mode next to any provider to see:

  1. Authorization Request -- the exact URL your app constructs, with every query parameter explained
  2. Callback -- the authorization code and state token received from the provider, with CSRF verification
  3. Token Exchange -- the server-to-server POST request body and the token response
  4. User Info -- the raw API response from the provider's userinfo endpoint
  5. Normalized Profile -- how your app maps provider-specific fields into a standard shape

Each step includes expandable explanations of what happened and why. No black box -- you see exactly what your code is doing.

git clone https://github.com/pranavkumaarofficial/oauth-for-dummies.git
cd oauth-for-dummies
pip install -e .
cp .env.example .env
# add at least one provider's credentials to .env
uvicorn app.main:app --reload
# open http://localhost:8000 and click "Learn Mode"

PKCE / OAuth 2.1

The project supports PKCE (Proof Key for Code Exchange), the key security improvement in OAuth 2.1. PKCE replaces the client secret with a cryptographic challenge, making OAuth safe for public clients (mobile apps, SPAs).

How it works

Instead of sending client_secret during token exchange, PKCE:

  1. Generates a random code_verifier (86 chars)
  2. Hashes it into a code_challenge (SHA-256, base64url)
  3. Sends the challenge with the authorization request
  4. Sends the verifier with the token exchange
  5. The provider verifies SHA256(verifier) == challenge

Enable PKCE on any provider

In the tutorial app, add one line to any provider class:

class MyProvider(OAuthProvider):
    use_pkce = True  # that's it

In the scaffold, add the provider key to the PKCE_PROVIDERS set in oauth_routes.py:

PKCE_PROVIDERS = {"my_provider"}

The Learn Mode debugger shows PKCE parameters (code_challenge, code_verifier) when enabled.


What is OAuth 2.0?

OAuth 2.0 is how "Login with Google" works. Instead of giving an app your password, you tell Google: "let this app see my name and email." The app never touches your password. It gets a temporary token instead.

+----------+                              +--------------+
|   You    |   "Login with GitHub" ---->  |  Your App    |
| (User)   |                              |  (FastAPI)   |
+----------+                              +------+-------+
                                                 |
                           +---------------------+
                           v
                   +---------------+
                   |    GitHub     |   "Allow this app?"
                   |  OAuth Server |   <-- You click "Yes"
                   +-------+-------+
                           |
                           v  sends authorization code
                   +---------------+
                   |  Your App     |   exchanges code for token
                   |  (server)     |   uses token to get your profile
                   +-------+-------+
                           |
                           v
                   You're logged in. No password shared. Ever.

That's the entire OAuth 2.0 Authorization Code flow. This project implements it for you.


How OAuth 2.0 Works

Here's the step-by-step flow that happens when a user clicks "Login with GitHub":

sequenceDiagram
    participant User
    participant App as Your FastAPI App
    participant GitHub as GitHub OAuth

    User->>App: Clicks "Login with GitHub"
    App->>GitHub: Redirects to /authorize (client_id, scope, state)
    GitHub->>User: Shows consent screen
    User->>GitHub: Clicks "Authorize"
    GitHub->>App: Redirects to /callback?code=abc&state=xyz
    App->>App: Verifies state parameter (CSRF protection)
    App->>GitHub: POST /access_token (code + client_secret)
    GitHub->>App: Returns access_token
    App->>GitHub: GET /user (Bearer token)
    GitHub->>App: Returns user profile (name, email, avatar)
    App->>User: Creates session, shows profile page

Key concepts:

Concept What it means
Authorization Code A short-lived, one-time code the provider sends to your app. Not the token itself.
Access Token The actual key your app uses to call the provider's API. Obtained by exchanging the code.
State Parameter A random string your app generates to prevent CSRF attacks. Verified on callback.
Scopes Permissions you request. read:user = profile info, user:email = email address.
Redirect URI The URL the provider sends the user back to. Must match exactly what you registered.
PKCE Proof Key for Code Exchange. Replaces client_secret with a cryptographic challenge. Required in OAuth 2.1.

Getting OAuth Credentials

GitHub

  1. Go to github.com/settings/developers
  2. Click "New OAuth App"
  3. Set callback URL to http://localhost:8000/auth/github/callback
  4. Copy Client ID and Client Secret into .env

Google

  1. Go to console.cloud.google.com/apis/credentials
  2. Click "Create Credentials" > "OAuth Client ID" > Web application
  3. Add redirect URI: http://localhost:8000/auth/google/callback
  4. Copy Client ID and Client Secret into .env

Discord

  1. Go to discord.com/developers/applications
  2. Create a new application > OAuth2
  3. Add redirect: http://localhost:8000/auth/discord/callback
  4. Copy Client ID and Client Secret into .env

Spotify

  1. Go to developer.spotify.com/dashboard
  2. Create an app > Edit Settings
  3. Add redirect URI: http://localhost:8000/auth/spotify/callback
  4. Copy Client ID and Client Secret into .env

Microsoft

  1. Go to portal.azure.com
  2. Register a new application > Web platform
  3. Add redirect URI: http://localhost:8000/auth/microsoft/callback
  4. Copy Application (client) ID and create a Client Secret in .env

LinkedIn

  1. Go to linkedin.com/developers/apps
  2. Create a new app > Auth tab
  3. Add redirect URL: http://localhost:8000/auth/linkedin/callback
  4. Copy Client ID and Client Secret into .env

API Reference

Routes

After running oauth-init, your app gets these endpoints for each configured provider:

Endpoint Method Description
/auth/{provider}/login GET Redirects user to the provider's OAuth consent screen
/auth/{provider}/callback GET Handles the redirect, exchanges code for token
/auth/logout GET Clears session cookie, redirects to home

Where {provider} is one of: github, google, discord, spotify, microsoft, linkedin.

Session Helper

from oauth_routes import get_session

@app.get("/dashboard")
async def dashboard(request: Request):
    user = get_session(request)
    if not user:
        return RedirectResponse("/auth/github/login")

    # user dict contains:
    # - id: str        (provider's user ID)
    # - name: str      (display name)
    # - email: str     (email address, may be None)
    # - avatar: str    (profile picture URL)
    # - provider: str  ("github", "google", "discord", etc.)

    return {"welcome": user["name"]}

CLI Reference

oauth-init                          # scaffold all providers + example app
oauth-init --provider github        # only GitHub OAuth
oauth-init --provider discord       # only Discord OAuth
oauth-init --no-example             # skip the example app, just routes + config
oauth-init --dir ./path/to/project  # scaffold into a specific directory

Available --provider values: github, google, discord, spotify, microsoft, linkedin.

Generated files:

File Purpose
oauth_config.py Loads provider credentials from .env, configures OAuth endpoints for all 6 providers
oauth_routes.py FastAPI router with login, callback, logout, session management, and PKCE support
oauth_example_app.py Complete working demo with login page and profile page
.env Template with environment variables for all providers

Security

The generated code includes these security measures out of the box:

  • CSRF protection via the state parameter (random token verified on callback)
  • PKCE support for OAuth 2.1 compliance (S256 code challenge)
  • HTTP-only cookies for session IDs (not accessible via JavaScript)
  • SameSite=Lax cookie policy (prevents cross-site request forgery)
  • Server-side token exchange (client secret never exposed to the browser)
  • One-hour session expiry (configurable via max_age)

Note: The generated code uses in-memory session storage. For production, swap _sessions dict for Redis, PostgreSQL, or your database of choice.


Project Structure

oauth-for-dummies/
|-- oauth_for_dummies/           # pip-installable CLI package
|   |-- cli.py                   # oauth-init command
|   +-- scaffold/                # template files dropped into your project
|       |-- oauth_config.py      # 6 provider configs
|       |-- oauth_routes.py      # routes + PKCE support
|       +-- oauth_example_app.py # demo with branded buttons
|
|-- app/                         # tutorial app (learning resource)
|   |-- main.py                  # FastAPI demo with UI
|   |-- config.py                # environment variable loader
|   |-- auth/
|   |   |-- routes.py            # auth route handlers
|   |   +-- storage.py           # session + debug session storage
|   +-- learn/
|       +-- routes.py            # OAuth debugger (Learn Mode) routes
|
|-- providers/                   # OAuth provider implementations
|   |-- base.py                  # abstract OAuthProvider class + PKCE
|   |-- github.py                # GitHub
|   |-- google.py                # Google
|   |-- discord.py               # Discord
|   |-- spotify.py               # Spotify
|   |-- microsoft.py             # Microsoft
|   |-- linkedin.py              # LinkedIn
|   +-- registry.py              # provider auto-discovery
|
|-- tests/                       # unit tests (20 tests, all passing)
|-- docs/                        # tutorials and diagrams
+-- pyproject.toml               # PyPI packaging configuration

Comparison with Other Libraries

oauth-for-dummies fastapi-oauth2 Authlib python-social-auth
What it is CLI scaffold + debugger Middleware library Production auth library Social auth framework
Approach Transparent (you own the code) Black box (middleware) Black box (library) Black box (framework)
Providers 6 Many (via social-core) Many Many
OAuth debugger Yes No No No
PKCE / OAuth 2.1 Yes No Yes No
Learn from it Yes (every HTTP request visible) No No No
Setup time 30 seconds 5 minutes 30+ minutes 30+ minutes
CLI scaffolding Yes No No No

When to use oauth-for-dummies: You want to understand OAuth, get started fast, and own the code without a runtime dependency.

When to use something else: You need 20+ providers, enterprise SSO (SAML), or a battle-tested library you don't want to maintain.


Tutorial

This repo includes a complete tutorial app that logs every step of the OAuth flow to your terminal:

git clone https://github.com/pranavkumaarofficial/oauth-for-dummies.git
cd oauth-for-dummies
pip install -e .
cp .env.example .env
# add your OAuth credentials to .env
uvicorn app.main:app --reload

You'll see output like this for every login:

============================================================
  STEP 1 -- Redirect user to GitHub
============================================================
  URL: https://github.com/login/oauth/authorize
  client_id:    abc12345...
  redirect_uri: http://localhost:8000/auth/github/callback
  scope:        read:user user:email
  state:        kF9x2mQp...
============================================================

See also:


Contributing

Contributions welcome. Some ideas:

  • Add a provider -- Twitter/X, Apple, Facebook, Twitch
  • Improve the CLI -- interactive mode, --framework flask support
  • Write tests for the scaffold files
  • Deploy the debugger -- host a public demo of Learn Mode

See CONTRIBUTING.md for setup instructions.


FAQ

Q: Is this production-ready? A: The generated code is fine for internal tools, prototypes, and small apps. For production at scale, swap the in-memory session store for a database and add HTTPS.

Q: Can I use this with Flask/Django? A: Not yet. Currently FastAPI only. Flask support is planned.

Q: What Python versions are supported? A: Python 3.9 and above.

Q: Do I need to understand OAuth to use this? A: No. Run oauth-init, add your keys to .env, and it works. But if you want to understand what's happening, use Learn Mode or read the tutorial.

Q: What is PKCE and do I need it? A: PKCE (Proof Key for Code Exchange) is a security improvement that replaces client_secret with a cryptographic challenge. It's required in OAuth 2.1 and recommended for all new apps. This project supports it out of the box.


License

MIT -- use it, learn from it, build on it.


If this saved you time, consider giving it a star on GitHub.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

oauth_for_dummies-1.1.0.tar.gz (22.8 kB view details)

Uploaded Source

Built Distribution

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

oauth_for_dummies-1.1.0-py3-none-any.whl (17.6 kB view details)

Uploaded Python 3

File details

Details for the file oauth_for_dummies-1.1.0.tar.gz.

File metadata

  • Download URL: oauth_for_dummies-1.1.0.tar.gz
  • Upload date:
  • Size: 22.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for oauth_for_dummies-1.1.0.tar.gz
Algorithm Hash digest
SHA256 27597ebdc5a0ae342b8e4815896caf294fcd776751e3c3a96dd814acf5769bec
MD5 d456186074da8e70b86cec41389ba1fa
BLAKE2b-256 8465d0a1f88ef79564e41e873b3c90df0495a3fab4415e685f229599759a0fb1

See more details on using hashes here.

Provenance

The following attestation bundles were made for oauth_for_dummies-1.1.0.tar.gz:

Publisher: publish.yml on pranavkumaarofficial/oauth-for-dummies

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oauth_for_dummies-1.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for oauth_for_dummies-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 de143dfb4a067c3be833afc84b20ae723d21bd0566c382f8bceebf9b6304ba5b
MD5 dfbb7789e2c9655361fc18af2b11a6d4
BLAKE2b-256 ea3919a5227e33aeed594c1fead58d2fde1e23430bf7d6d50932afde83e6bf92

See more details on using hashes here.

Provenance

The following attestation bundles were made for oauth_for_dummies-1.1.0-py3-none-any.whl:

Publisher: publish.yml on pranavkumaarofficial/oauth-for-dummies

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page