Protect your API on Python
Extract the Bearer Token from request header
"""requires-auth.py
"""
def get_auth_token():
auth = request.headers.get("Authorization", None)
if not auth:
raise Error({ code: 'auth.authorization_header_missing', status: 401 })
contents = auth.split()
if len(contents) < 2
raise Error({code: 'auth.authorization_token_invalid_format', status: 401})
elif contents[0] != 'Bearer'
raise Error({code: 'auth.authorization_token_type_not_supported', status: 401})
return contents[1]
Token validation
For demonstration, we use the Flask app and jose package to create the require_auth decorator to validate the token's signature, expiration status, and required claims.
Install jose as your dependency
pip install python-jose[rsa]
Retrieve Auth’s OIDC configurations
You will need a JWK public key set and the token issuer to verify the signature and source of the received JWS token. All the public Auth Authorization Configurations can be found at https://your-auth-domain/.well-known/openid-configuration.
e.g. Call https://nightly-accounts-api.complyment.com/.well-known/openid-configuration. And locate the following two fields in the response body:
{
"jwks_uri": "https://nightly-accounts-api.complyment.com/.well-known/jwks.json",
"issuer": "https://nightly-accounts-api.complyment.com"
}
Create the authorization validation decorator using the Auth’s configurations
"""requires-auth.py
"""
import json
from flask import request, _request_ctx_stack
from six.moves.urllib.request import urlopen
from functools import wraps
from jose import jwt
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
token = get_token_auth_header()
# jwks_uri endpoint retrieved from Auth
jwks_uri = urlopen('https://nightly-accounts-api.complyment.com/.well-known/jwks.json')
# issuer retrieved from Auth
issuer = 'https://<your-auth-domain>'
jwks = json.loads(jwks_uri.read())
try:
payload = jwt.decode(
token,
jwks,
algorithms='RS256',
audience='<your request listener resource indicator>',
issue=issuer
options={
'verify_at_hash': False
}
)
except Exception:
# exception handler
raise Error({code: 'invalid_token', status: 401})
# Custom code to process payload
_request_ctx_stack.top.user_id = payload.get('sub')
return f(*args, **kwargs)
return decorated
Apply decorator to your API
from flask import Flask
from flask_cors import cross_origin
APP = Flask(__name__)
@APP.route("/user/info")
@cross_origin(headers=["Content-Type", "Authorization"])
@requires_auth
def api:
# Your API Logic
Last updated