Skip to content

feat(auth): add OAuth2 client credentials support (alpha) - #8486

Open
bfreiberg wants to merge 2 commits into
aws-powertools:developfrom
bfreiberg:feat/auth-alpha-oauth2-8466
Open

bfreiberg wants to merge 2 commits into
aws-powertools:developfrom
bfreiberg:feat/auth-alpha-oauth2-8466

Conversation

@bfreiberg

@bfreiberg bfreiberg commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Issue number: Follow-up to #8466 and #8469; implements the deferred outbound OAuth client.

Summary

Lambda functions calling an OAuth2-protected API currently need to manage token exchange, secret retrieval, token lifetimes, and concurrent refresh themselves. This adds OAuth2Client under utilities.auth_alpha.oauth2

Changes

  • Support the client_credentials grant with client_secret_basic, configurable scopes, and mutually exclusive audience or RFC 8707 resource selection.
  • Keep token caches private to each client. Reacquire tokens on demand when 30 seconds remain, coordinate concurrent exchanges, and avoid caching tokens with short or missing lifetimes.
  • Accept a secret string or callable, invoking the callable on each exchange attempt so applications can use Parameters or another secret provider.
  • Provide auth_headers() for application-owned HTTP clients and a synchronous HTTPS request() helper. Disable redirects and downstream retries, reject competing Authorization headers, and use separate acquisition and downstream budgets.
  • Share credential-free errors and transport helpers with JWT verification, preserving existing JWT exception imports. Check response-read deadlines through headers, bodies, and chunked framing; keep the existing JSON response-size limit.
  • Add a lazy [oauth2] extra requiring only urllib3, dependency-isolation tests, functional and local TLS tests, Lambda examples, API documentation, and a downstream MCP example.

Only client-credentials acquisition is included. Interactive grants, delegated token exchange, introspection, other client authentication methods, and a native async API remain outside this change.

User experience

Install aws-lambda-powertools[oauth2] and configure a client outside the Lambda handler:

import os

from aws_lambda_powertools.utilities.auth_alpha import OAuth2Client

inventory_api = OAuth2Client(
    token_url=os.environ["TOKEN_URL"],
    client_id=os.environ["CLIENT_ID"],
    client_secret=lambda: os.environ["CLIENT_SECRET"],
    resource="https://inventory.example.com",
    scopes=["inventory:read"],
)


def lambda_handler(event, context):
    response = inventory_api.request(
        "GET", "https://inventory.example.com/stock", timeout=5,
    )
    if response.status != 200:
        raise RuntimeError("Inventory lookup failed")
    return response.json()

Applications can instead obtain headers with inventory_api.auth_headers(). The guide includes a Parameters secret loader, testing examples, and guidance on trusted destinations, secret rotation, provider resource selection, and timeout limitations. The namespace remains experimental and its API may change before GA.

Validation

  • Full non-performance suite on Python 3.14: 3,047 passed, 4 existing skips, 96.77% coverage.
  • Authentication functional and real TLS tests on Python 3.10 and 3.12: 473 passed on each version. TLS cases cover certificate trust, redirects, response limits, slow headers/body/chunk framing, concurrent deadlines, and recovery after timeouts.
  • Lambda examples: 7 passed. Performance suite: 10 passed when run independently. Two existing Metrics tests with a 2 ms SLA exceeded that threshold while running alongside the package build, then passed in isolation.
  • JWT-only and OAuth-only Nox dependency sessions pass; OAuth imports and operates without PyJWT or cryptography.
  • Ruff formatting/lint, mypy, ty, Bandit, complexity limits, staged Gitleaks scan, Poetry lock validation, wheel/sdist builds, Markdown lint, and the documentation build pass.
  • Independent implementation and specification reviews completed; identified issues were addressed and covered by regression tests.

Validation uses a local TLS token endpoint. Live identity-provider interoperability and AWS deployment tests were not run. The documentation build retains existing warnings about unrelated links and external assets.


By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Disclaimer: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful.

@powertools-for-aws-oss-automation powertools-for-aws-oss-automation Bot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Sep 24, 2026
@boring-cyborg boring-cyborg Bot added dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation tests labels Sep 24, 2026
Comment thread aws_lambda_powertools/utilities/auth_alpha/oauth2/client.py Fixed
@sonarqubecloud

Copy link
Copy Markdown

@bfreiberg
bfreiberg marked this pull request as ready for review September 24, 2026 13:41
@bfreiberg
bfreiberg requested a review from a team as a code owner September 24, 2026 13:41
@bfreiberg
bfreiberg requested a review from svozza September 24, 2026 13:41
@powertools-for-aws-oss-automation

Copy link
Copy Markdown

Referenced issues are closed or don't exist. Please ensure there is an open issue related to this change to avoid significant delays or closure.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants