fix(keycardai-oauth): warn once when a TokenVerifier is built without an audience (SDK-4) - #319
Merged
Merged
Conversation
… an audience (SDK-4) TokenVerifier(audience=None) now emits one MissingAudienceWarning at construction naming the option to set. Behavior with an audience is unchanged; no signature change. Co-Authored-By: Larry Osakwe <larry@keycard.ai>
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Larry-Osakwe
approved these changes
Sep 17, 2026
Larry-Osakwe
left a comment
Contributor
There was a problem hiding this comment.
Single warning site in TokenVerifier, covered by pytest.warns and two silent cases, providers pass through untouched, and the mcp README snippets all bind an audience. Export from keycardai.oauth.server instead of the top level is right: VerifierConfigError is not top-level either.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the spec-version 2 construction rule from keycard-sdk-spec
specs/server-bearer-auth/bearer-token-verification-middleware.md(SDK-4): building the bearer middleware or the verifier it wraps without an audience emits exactly one warning at construction, naming the option to set, never per request. Behavior when an audience is configured does not change.Fix-level change: additive warning, no signature change.
The single site covers
keycardai-starlette(provider.pyget_token_verifier) andkeycardai-mcp(server/auth/provider.pyget_token_verifier), which pass theiraudiencethrough; no second warning there.keycardai-langchainalways passesaudience=resourceandkeycardai-fastmcpderives its own audience, so neither changes.Export:
MissingAudienceWarningis exported fromkeycardai.oauth.server(whereTokenVerifieritself is exported). The brief asked forkeycardai.oauth"alongsideVerifierConfigError", butVerifierConfigErroris not exported at the top level, and importing.server.exceptionsfromkeycardai/oauth/__init__.pytriggers the existingcredentials.py -> keycardai.oauthcircular import (ImportError: cannot import name 'ClientConfig' from partially initialized module), so the top-level export is not added.Docs:
packages/mcp/README.md:audience="http://localhost:8000/mcp"on all twelveAuthProvider(snippets, plus one sentence after the Quick Start explaining it.packages/starlette/README.md: the "leavingaudienceunset disables the check" paragraph now says it also warns once at construction.packages/starlette/src/keycardai/starlette/routers/metadata.py: theprotected_routerdocstring example passes an audience.packages/fastmcp/README.mduntouched (audience derived frommcp_base_url).Tests (
packages/oauth/tests/keycardai/oauth/server/test_verifier.py):pytest.warns(MissingAudienceWarning)exactly once without an audience;warnings.catch_warnings(record=True)empty with astraudience and with adictaudience; the export check. No package's pytest config turns warnings into errors (packages/mcponly ignores websockets/uvicorn deprecations), so existing fixtures without an audience keep passing and only gain a warning in the summary.Verification
just check: All checks passed.just typecheck: All checks passed (all seven packages).uv run --frozen pytest testsfrom each package directory): oauth 535 passed, starlette 121 passed, langchain 89 passed, mcp 582 passed / 18 skipped / 2 failed. The two mcp failures (test_auth_provider_init_with_zone_id,test_no_application_credential_does_enable_registration) reproduce with this change stashed; they assertNoneAuthwhen no credential is passed, but the shell'sKEYCARD_CLIENT_ID/SECRETare discovered into aBasicAuth. Same pre-existing pair noted on fix(keycardai-starlette): stop rewriting the proxied authorization_endpoint (SDK-3) #316.Link to Devin session: https://app.devin.ai/sessions/bbc062cf32b548ef9c4b8b444d2ec67f
Open in Devin Desktop: https://app.devin.ai/desktop/session/bbc062cf32b548ef9c4b8b444d2ec67f?variant=devin
Requested by: @Larry-Osakwe