Skip to main content

Flask JWT OIDC

Simple OIDC JWT extension to protect APIs

This is a fairly simple extension that should require minimal setup for OIDC standard services.

Currently it's testing against Keycloak, but will be adding in example configs and testing for:

  • Keycloak

Alternatives

There are some great alternatives that are not so opinionated and provide more support for general JWTs Check out: Flask-JWT-Simple

Example(s)

There is one example under example/flask_app It uses pytest and sets up a dummy JWT to be used in the tests.

Configuration

Create a .env file, or OS configmap, shell exports, etc.

#.env
export JWT_OIDC_WELL_KNOWN_CONFIG="https://KEYCLOAK-SERVICE/auth/realms/REALM-NAME/.well-known/openid-configuration"
export JWT_OIDC_AUDIENCE="keycloak-client"
export JWT_OIDC_CLIENT_SECRET="keycloak-client-secret"

Create a config file, that reads in the environment variables:

# config.py

from os import environ as env
from dotenv import load_dotenv, find_dotenv


ENV_FILE = find_dotenv()
if ENV_FILE:
    load_dotenv(ENV_FILE)

class Config(object):

    JWT_OIDC_WELL_KNOWN_CONFIG = env.get('JWT_OIDC_WELL_KNOWN_CONFIG')
    JWT_OIDC_AUDIENCE = env.get('JWT_OIDC_AUDIENCE')
    JWT_OIDC_CLIENT_SECRET = env.get('JWT_OIDC_CLIENT_SECRET')

Create a flask script that to use the JWT services

Note: that roles can be checked as either decorators managing access to the function, or as a function call that returns True/False for finer grained access control in the body of the function.

# app.py

from flask import Flask, jsonify
from flask_cors import cross_origin
from config import Config
from flask_jwt_oidc import AuthError, JwtManager


app = Flask(__name__)

app.config.from_object(Config)

def get_roles(dict):
    return dict['realm_access']['roles']
app.config['JWT_ROLE_CALLBACK'] = get_roles

jwt = JwtManager(app)

@app.route("/api/secure")
@cross_origin(headers=["Content-Type", "Authorization"])
@cross_origin(headers=["Access-Control-Allow-Origin", "*"]) # IRL you'd scope this to set domains
@jwt.requires_auth
def secure():
    """A Bearer JWT is required to get a response from this endpoint
    """
    return jsonify(message="The is a secured endpoint. You provided a valid Bearer JWT to access it.")


@app.route("/api/secured-and-roles")
@cross_origin(headers=["Content-Type", "Authorization"])
@cross_origin(headers=["Access-Control-Allow-Origin", "*"]) # IRL you'd scope this to a real domain
@jwt.requires_auth
def secure_with_roles():
    """valid access token and assigned roles are required
    """
    if jwt.validate_roles("names_editor"):
        return jsonify(message="This is a secured endpoint, where roles were examined in the body of the procedure! "
                               "You provided a valid JWT token")

    raise AuthError({
        "code": "Unauthorized",
        "description": "You don't have access to this resource"
    }, 403)


@app.route("/api/secured-decorated-roles")
@cross_origin(headers=["Content-Type", "Authorization"])
@cross_origin(headers=["Access-Control-Allow-Origin", "*"]) # IRL you'd scope this to a real domain
@jwt.requires_roles("names_editor")
def secure_deco_roles():
    """valid access token and assigned roles are required
    """
    return jsonify(message="This is a secured endpoint. "
                           "The roles were checked before entering the body of the procedure! "
                           "You provided a valid JWT token")


if __name__ == "__main__":
    app.run()

TODO

  • add tests
  • add more examples
  • add tests for the OIDC service providers listed above

Metadata

Release files for flask-jwt-oidc 0.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for flask-jwt-oidc 0.9.0
File Size Uploaded
flask_jwt_oidc-0.9.0.tar.gz 7.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for flask-jwt-oidc 0.9.0
File Interpreter ABI Platform
flask_jwt_oidc-0.9.0-py3-none-any.whl Python 3 none any Details

Total release size: 17.2 kB

Release files / flask_jwt_oidc-0.9.0.tar.gz

Download URL flask_jwt_oidc-0.9.0.tar.gz
Size 7.5 kB
Tags Source
SHA-256 checksum
How to use checksums
6c6169b52b73dbdc06f2e11b9481f382c4125a1b181f88f7270992200cda69a3
BLAKE2b-256 checksum
How to use checksums
8f598827de70afedb42ce19c28aeb2d166e9751538f5b7fa5b6303354ff6fb5d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 14, 2026.

Transparency log

Release files / flask_jwt_oidc-0.9.0-py3-none-any.whl

Download URL flask_jwt_oidc-0.9.0-py3-none-any.whl
Size 9.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7ce75f002e7a1ef3639366bf03f62b86e9a3afbd2d1818cbcb71a196b027e55c
BLAKE2b-256 checksum
How to use checksums
040885dde23b8855e8beb1a5014632fcf8da20242e99669af9fc4c1432bf1a64
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 14, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.9.0 This release

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.5

2 release files

0.1.3

3 release files

0.1.2

2 release 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