Examples#

This page provides practical examples of using axioms-flask-py decorators to secure your Flask API routes.

Scope-Based Authorization#

Check if openid or profile scope is present in the token:

from flask import Blueprint, jsonify
from axioms_flask.decorators import has_valid_access_token, has_required_scopes

private_api = Blueprint("private_api", __name__)

@private_api.route('/private', methods=["GET"])
@has_valid_access_token
@has_required_scopes(['openid', 'profile'])
def api_private():
    return jsonify({'message': 'All good. You are authenticated!'})

Example JWT Token Payload (Success):

{
  "sub": "user123",
  "aud": "your-api-audience",
  "scope": "openid profile email",
  "exp": 1735689600,
  "iat": 1735686000
}

This request will succeed because the token contains openid in the scope claim.

Example JWT Token Payload (Failure):

{
  "sub": "user123",
  "aud": "your-api-audience",
  "scope": "email",
  "exp": 1735689600,
  "iat": 1735686000
}

This request will fail with 403 Forbidden because the token does not contain openid or profile in the scope claim.

Role-Based Authorization#

Check if sample:role role is present in the token:

from flask import Blueprint, jsonify, request
from axioms_flask.decorators import has_valid_access_token, has_required_roles

role_api = Blueprint("role_api", __name__)

@role_api.route("/role", methods=["GET", "POST", "PATCH", "DELETE"])
@has_valid_access_token
@has_required_roles(["sample:role"])
def sample_role():
    if request.method == 'POST':
        return jsonify({"message": "Sample created."})
    if request.method == 'PATCH':
        return jsonify({"message": "Sample updated."})
    if request.method == 'GET':
        return jsonify({"message": "Sample read."})
    if request.method == 'DELETE':
        return jsonify({"message": "Sample deleted."})

Example JWT Token Payload (Success):

{
  "sub": "user123",
  "aud": "your-api-audience",
  "roles": ["sample:role", "viewer"],
  "exp": 1735689600,
  "iat": 1735686000
}

This request will succeed because the token contains sample:role in the roles claim.

Example JWT Token Payload with Namespaced Claims (Success):

{
  "sub": "user123",
  "aud": "your-api-audience",
  "https://your-domain.com/claims/roles": ["sample:role", "admin"],
  "exp": 1735689600,
  "iat": 1735686000
}

This request will also succeed if AXIOMS_DOMAIN is set to your-domain.com.

Example JWT Token Payload (Failure):

{
  "sub": "user123",
  "aud": "your-api-audience",
  "roles": ["viewer", "editor"],
  "exp": 1735689600,
  "iat": 1735686000
}

This request will fail with 403 Forbidden because the token does not contain sample:role.

Permission-Based Authorization#

Check permissions at the API method level:

from flask import Blueprint, jsonify
from axioms_flask.decorators import has_valid_access_token, has_required_permissions

permission_api = Blueprint("permission_api", __name__)

@permission_api.route("/permission", methods=["POST"])
@has_valid_access_token
@has_required_permissions(["sample:create"])
def sample_create():
    return jsonify({"message": "Sample created."})


@permission_api.route("/permission", methods=["PATCH"])
@has_valid_access_token
@has_required_permissions(["sample:update"])
def sample_update():
    return jsonify({"message": "Sample updated."})


@permission_api.route("/permission", methods=["GET"])
@has_valid_access_token
@has_required_permissions(["sample:read"])
def sample_read():
    return jsonify({"message": "Sample read."})


@permission_api.route("/permission", methods=["DELETE"])
@has_valid_access_token
@has_required_permissions(["sample:delete"])
def sample_delete():
    return jsonify({"message": "Sample deleted."})

Example JWT Token Payload (Success for sample:read):

{
  "sub": "user123",
  "aud": "your-api-audience",
  "permissions": ["sample:read", "sample:update"],
  "exp": 1735689600,
  "iat": 1735686000
}

This request will succeed for the GET endpoint because the token contains sample:read in the permissions claim.

Example JWT Token Payload with Namespaced Claims (Success):

{
  "sub": "user123",
  "aud": "your-api-audience",
  "https://your-domain.com/claims/permissions": ["sample:create", "sample:delete"],
  "exp": 1735689600,
  "iat": 1735686000
}

This request will succeed for POST and DELETE endpoints if AXIOMS_DOMAIN is set to your-domain.com.

Example JWT Token Payload (Failure):

{
  "sub": "user123",
  "aud": "your-api-audience",
  "permissions": ["other:read"],
  "exp": 1735689600,
  "iat": 1735686000
}

This request will fail with 403 Forbidden because the token does not contain any of the required sample:* permissions.

Complete Flask Application#

For a complete working example, check out the Flask sample application on GitHub. The sample demonstrates a fully functional Flask application with authentication and authorization.