Guide: Python
Step 1: Extract the Bearer Token from request header
A authorized request should contain an Authorization
header with Bearer <access_token>
as its content. Extract the Authorization Token from the 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]
Step 2: 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 python-jose
as your dependency
Pick the cryptography your are using in Logto. (ecdsa
by default)
pip install python-jose[ecdsa]
Retrieve Logto'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 latest public Logto Authorization Configurations can be found at https://<your-logto-domain>/oidc/.well-known/openid-configuration
.
e.g. Call https://tenant-id.logto.app/oidc/.well-known/openid-configuration
. And locate the following two fields in the response body:
{
"jwks_uri": "https://tenant-id.logto.app/oidc/jwks",
"issuer": "https://tenant-id.logto.app/oidc"
}
Create the authorization validation decorator
If you use Role-based access control, scope validation is also required.
"""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 Logto
jwks_uri = urlopen('https://<your-logto-domain>/oidc/jwks')
# issuer retrieved from Logto
issuer = 'https://<your-logto-domain>/oidc'
jwks = json.loads(jwks_uri.read())
try:
payload = jwt.decode(
token,
jwks,
# The jwt encode algorithm retrieved along with jwks. ES384 by default
algorithms=jwt.get_unverified_header(token).get('alg'),
# The API's registered resource indicator in Logto
audience='<your request listener resource indicator>',
issuer=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