Flask-OIDC

2.4.0 · active · verified Sat Apr 11

Flask-OIDC is an extension to Flask that allows you to add OpenID Connect based authentication to your website. It is currently at version 2.4.0 and sees regular releases, with several updates in the past year, indicating active maintenance and development.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates a basic Flask application integrated with Flask-OIDC. It configures the OIDC extension, protects a route using `oidc.require_login`, and provides simple login/logout functionality. Configuration details for your OIDC provider are expected in a `client_secrets.json` file. Ensure `FLASK_SECRET_KEY` and the `client_secrets.json` path are set, ideally via environment variables, and configure `OIDC_REDIRECT_URI` to match your registered callback URL.

import os
from flask import Flask, redirect, url_for, render_template_string, g, session
from flask_oidc import OpenIDConnect

app = Flask(__name__)
app.config.update({
    'SECRET_KEY': os.environ.get('FLASK_SECRET_KEY', 'a_very_secret_key_that_should_be_random'),
    'OIDC_CLIENT_SECRETS': os.environ.get('OIDC_CLIENT_SECRETS_FILE', './client_secrets.json'),
    'OIDC_REDIRECT_URI': os.environ.get('OIDC_REDIRECT_URI', 'http://localhost:5000/oidc_callback'),
    'OIDC_SCOPES': ['openid', 'email', 'profile'],
    'OIDC_COOKIE_SECURE': False, # Use True in production with HTTPS
    'OIDC_CALLBACK_ROUTE': '/oidc_callback', # The default callback route.
    'OIDC_REQUIRE_VERIFIED_EMAIL': False # Set to True for stricter validation
})

oidc = OpenIDConnect(app)

HTML_TEMPLATE = '''
<!doctype html>
<html lang="en">
<head><meta charset="utf-8"></head>
<body>
    {% if g.oidc_user.is_authenticated() %}
        Hello, {{ g.oidc_user.userinfo.get('preferred_username', 'User') }}!
        <a href="{{ url_for('private') }}">Access Protected Area</a>
        <a href="{{ url_for('oidc_logout') }}">Log Out</a>
    {% else %}
        Welcome, anonymous user!
        <a href="{{ url_for('private') }}">Log In</a>
    {% endif %}
</body>
</html>
'''

@app.route('/')
def index():
    return render_template_string(HTML_TEMPLATE)

@app.route('/private')
@oidc.require_login # Protect this route.
def private():
    return f"Hello, {g.oidc_user.userinfo.get('email')}! This is a protected area."

@app.route('/logout')
def oidc_logout():
    oidc.logout()
    return redirect(url_for('index'))

# Example client_secrets.json content (create this file next to your app.py):
# {
#   "web": {
#     "client_id": "YOUR_CLIENT_ID",
#     "client_secret": "YOUR_CLIENT_SECRET",
#     "auth_uri": "YOUR_PROVIDER_AUTH_URI",
#     "token_uri": "YOUR_PROVIDER_TOKEN_URI",
#     "userinfo_uri": "YOUR_PROVIDER_USERINFO_URI",
#     "issuer": "YOUR_PROVIDER_ISSUER",
#     "redirect_uris": ["http://localhost:5000/oidc_callback"],
#     "token_introspection_uri": "YOUR_PROVIDER_TOKEN_INTROSPECTION_URI" (optional)
#   }
# }

if __name__ == '__main__':
    # For local development, ensure OIDC_CLIENT_SECRETS_FILE points to a valid file.
    # Replace with your actual OIDC provider details in client_secrets.json
    # And set FLASK_SECRET_KEY in your environment.
    # export FLASK_SECRET_KEY="a_strong_random_secret_key"
    # If using HTTP (not recommended for production), set OIDC_COOKIE_SECURE to False.
    # Otherwise, ensure your application runs over HTTPS.
    app.run(debug=True, port=5000)

view raw JSON →