Skip to content

fix(auth): synthesize AuthInfo(kind="bearer") in _build_request_context#577

Merged
bokelley merged 1 commit intomainfrom
bokelley/issue-576-bearer-auth-info
May 4, 2026
Merged

fix(auth): synthesize AuthInfo(kind="bearer") in _build_request_context#577
bokelley merged 1 commit intomainfrom
bokelley/issue-576-bearer-auth-info

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

@bokelley bokelley commented May 4, 2026

Closes #576

Summary

Completes the bearer-adopter typed surface started by #574. PR #574 made ctx.auth_principal populate from the BearerTokenAuthMiddleware ContextVar; this PR addresses the deeper structural gap — ctx.auth_info itself was None on bearer flows, so adopters couldn't branch on ctx.auth_info.kind to discriminate signed-request vs bearer.

Mechanic

_build_request_context now synthesizes AuthInfo(kind="bearer", principal=<from current_principal>, credential=None) when no AuthInfo is supplied and the bearer ContextVar is populated.

credential=None is passed explicitly to bypass the AuthInfo.__post_init__ flat-field synthesis path and its accompanying DeprecationWarning — see context.py:396-426: the sentinel default fires synthesis, an explicit None does not. This makes the synthesis future-proof past the 4.5.0 synthesis removal.

The synthesized AuthInfo carries only kind + principal — bearer tokens are opaque to the SDK, so we don't know key_id / scopes. Adopters who want richer data can write their own context_factory.

Behavior shift

Bearer adopters: ctx.auth_info: None → AuthInfo(kind="bearer", ...). Adopter code that gated on if ctx.auth_info is None to detect bearer flow now needs ctx.auth_info.kind == "bearer" instead. Mirrors the #574 callout style.

Test plan

  • Extended test_build_request_context_falls_back_to_bearer_context_var to assert ctx.auth_info.kind == "bearer" and ctx.auth_info.principal == bearer_principal
  • Added test_build_request_context_bearer_auth_info_does_not_warn pinning the no-DeprecationWarning behavior (the spike's "(b) is clean" claim)
  • test_build_request_context_auth_info_takes_precedence_over_bearer_var still passes — explicit AuthInfo wins over the bearer fallback
  • Full suite: pytest tests/ — 4168 passed, 24 skipped, 1 xfailed
  • ruff check src/, mypy src/adcp/ — clean

…xt for bearer flows

Completes the bearer-adopter typed surface started by #574. PR #574
made ctx.auth_principal populate from the BearerTokenAuthMiddleware
ContextVar; this addresses the deeper structural gap — ctx.auth_info
itself was None on bearer flows, so adopters couldn't branch on
ctx.auth_info.kind to discriminate signed-request vs bearer.

_build_request_context now synthesizes
AuthInfo(kind="bearer", principal=<from current_principal>,
credential=None) when no AuthInfo is supplied and the bearer ContextVar
is populated. credential=None is passed explicitly to bypass the
AuthInfo.__post_init__ flat-field synthesis path and its accompanying
DeprecationWarning (see context.py:396-426: the sentinel default fires
synthesis, an explicit None does not). The synthesized AuthInfo carries
only kind + principal — bearer tokens are opaque to the SDK; adopters
who want richer data (key_id, scopes) can write their own
context_factory.

User-visible behavior shift for bearer adopters:
ctx.auth_info: None → AuthInfo(kind="bearer", ...). Adopter code that
gated on `if ctx.auth_info is None` to detect bearer flow now needs
`ctx.auth_info.kind == "bearer"` instead — mirrors the #574 callout
style.

Closes #576
@bokelley bokelley force-pushed the bokelley/issue-576-bearer-auth-info branch from 0ce47f3 to 10927fe Compare May 4, 2026 14:50
@bokelley bokelley merged commit c2ab696 into main May 4, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BearerTokenAuthMiddleware does not construct AuthInfo — ctx.auth_info.kind unusable for bearer flows

1 participant