Skip to main content

Opinionated flask oidc client

Project description

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
  • dex
  • Google
  • Amazon IAM
  • Auth0

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

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

flask_jwt_oidc-0.7.0.tar.gz (7.6 kB view details)

Uploaded Source

Built Distribution

flask_jwt_oidc-0.7.0-py3-none-any.whl (9.5 kB view details)

Uploaded Python 3

File details

Details for the file flask_jwt_oidc-0.7.0.tar.gz.

File metadata

  • Download URL: flask_jwt_oidc-0.7.0.tar.gz
  • Upload date:
  • Size: 7.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.12.2 Darwin/23.4.0

File hashes

Hashes for flask_jwt_oidc-0.7.0.tar.gz
Algorithm Hash digest
SHA256 ba90e3557e931b1c5cbd37fb2ddc462a525f74e2a85aa7d684a733e68fa9a3e4
MD5 2f07e66dd83b7d6e8b7798d36f44b7d2
BLAKE2b-256 cc207c1f54c7167f0ce91feb26fa0485b358b5470fb7de5c3b482284e537ae08

See more details on using hashes here.

File details

Details for the file flask_jwt_oidc-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: flask_jwt_oidc-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 9.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.12.2 Darwin/23.4.0

File hashes

Hashes for flask_jwt_oidc-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0fec097ea0557fe315ca576f4c9a795c874bf28ae62b21eadf4626c5c5ca9029
MD5 9328dd8a24770bed045c1cb1dbd3a15f
BLAKE2b-256 43cc2cd98997fc9573eec24865e6e78ec203970cc40b9b5071d3dda8714b60be

See more details on using hashes here.

Supported by

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