Skip to content

RFC: Generic Authorizer Support in Lambda Powertools Router #7477

@tonnico

Description

@tonnico

Is this related to an existing feature request or issue?

No response

Which Powertools for AWS Lambda (Python) utility does this relate to?

Event Handler - REST API

Summary

This RFC proposes extending the Lambda Powertools Router and APIGatewayRestResolver to support authorization metadata on routes and introduce a pluggable Authorizer framework.
This enables developers to declare authorization requirements directly alongside route definitions, and delegate enforcement to customizable authorizer classes.

The framework should:

  • Be generic (not tied to a single provider like Amazon Verified Permissions).
  • Provide built-in integrations (e.g., AVP, MSAL/Azure AD).
  • Allow teams to implement custom authorizers (e.g., Cognito groups, DynamoDB RBAC).

Use case

  • Developers want to centralize authorization logic without duplicating route definitions.
  • Applications may use multiple routers or a single APIGatewayRestResolver.
  • Authorization metadata should travel with routes (including when routers are mounted with a prefix).
  • Organizations often require different backends for authorization:
    • Amazon Verified Permissions (AVP).
    • Token claims (Cognito, Azure AD via MSAL).
    • Custom RBAC (DynamoDB, configuration).

Example today:

  • Developers must implement a separate Lambda Authorizer and maintain parallel route → action mappings.
  • This creates drift and duplication.

With proposal:

@app.get("/orders/<orderId>", authorize={"action": "orders:read", "resource": "order:{orderId}"})
def get_order(orderId: str): ...

Proposal

  1. Extend route registration

    • Add an optional authorize kwarg to methods.

    • Example:

      @app.post("/users", authorize={"action": "users:create", "resource": "user:*"})
      def create_user(): ...
    • Internally, this metadata is stored alongside the route definition.

  2. Authorizer Baseclass

    • Introduce a BaseAuthorizer contract:

      class BaseAuthorizer(ABC):
          def __init__(self, app): ...
          def handle(self, event, context): ...
          @abstractmethod
          def extract_principal(self, event): ...
          @abstractmethod
          def evaluate_route(self, route_meta, principal, token, extra_ctx): ...
          @abstractmethod
          def build_policy(self, principal, event, allowed): ...
  3. Developer workflow

    • Add routes with authorize=....

    • Instantiate an authorizer with the app.

    • Reference the authorizer in Lambda:

      class AVPAuthorizer(BaseAuthorizer): ...
      
      app = APIGatewayRestResolver()
      authorizer = AVPAuthorizer(app, policy_store_id="ps-123456")
      
      def app_handler(event, context):
          return app.resolve(event, context)
      
      def authorizer_handler(event, context):
          return authorizer.handle(event, context)

Out of scope

  • Policy modeling for AVP: developers must design and manage AVP schemas and policies separately.
  • Token validation libraries: Powertools should not ship MSAL, PyJWT, or similar; implementations can import them.
  • Non-API Gateway events: initial scope is for API Gateway + Lambda Authorizer patterns.

Potential challenges

  1. Metadata typing

    • Should authorize accept dict, TypedDict, or a BaseModel?
    • Proposal: accept dict | TypedDict publicly, normalize internally to a structured class for consistency.
  2. Extensibility without lock-in

    • Ensure AVP is not “baked in”, it should be a first-party authorizer, not the only way.
  3. Performance

    • Batch evaluation (e.g., AVP is_authorized_batch) is preferable in proxy+ integrations.
    • Need to design efficient helpers for this.
  4. Developer ergonomics

    • Minimize boilerplate, adding authorize=... should feel as natural as adding a route.

Dependencies and Integrations

  • Core: No additional runtime dependencies required.
  • AVPAuthorizer: requires boto3 (optional pyjwt)
  • MSALAuthorizer: requires msal or pyjwt (optional extras).

Alternative solutions

  1. Custom Lambda Authorizer without Powertools integration

    • Developers maintain separate route → action mappings manually.
    • Risk of drift, harder to maintain.
  2. Middleware approach

    • Authorization logic in before() handlers or decorators.
    • Works but doesn’t integrate well with API Gateway native authorizers (policy documents).

Acknowledgment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Ideas

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions