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
    No fields configured for issues without a type.

    Projects

    Status

    Ideas

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions