You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adapters (authplane-mcp, authplane-fastmcp):
- Forward a DPoPRequestContext from verify_token to AuthplaneResource.verify
so inbound_dpop=InboundDPoPOptions(required=True) enforces the proof check
end-to-end. htu origin is always the operator-configured resource URI, never
the inbound Host / X-Forwarded-Proto headers.
- Reconstruct htu from scope["raw_path"] to preserve percent-encoding (e.g.
%2F) on the wire under ASGI, falling back to request.url.path.
- authplane-mcp adds AuthplaneRequestContextMiddleware, get_current_request(),
and install_request_context(mcp) (idempotent) to publish the active request
on a ContextVar so the verifier can build a DPoPRequestContext.
- Cache the in-flight verify task per request on request.state so a repeat
verify_token within the same request reuses it instead of re-entering the
inbound DPoP replay store. Cross-request replay protection is unaffected.
Core (authplane):
- Bound TokenCache with a configurable max_entries cap (default 10_000,
exposed as TokenCache.DEFAULT_MAX_ENTRIES) and LRU eviction; plumbed
through AuthplaneClient.create(cache_max_entries=...).
- Add VerifiedClaims.require_scopes(scopes) plural AND-style scope helper.
Empty input is a no-op; raises InsufficientScopeError listing all missing
scopes and the token's available scopes on failure.
- Export TokenCache from authplane.__init__.
- require_scope (singular) now renders an empty scope set as (none) instead
of [], consistent with the plural helper.
Docs and demos run adapter setup, the async server entry point, and aclose()
in a single asyncio.run(main()), keeping the client's locks, HTTP pool, and
background refresh tasks on one event loop.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+13Lines changed: 13 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
8
8
## [Unreleased]
9
9
10
+
### Added
11
+
-`TokenCache` is now bounded by a configurable `max_entries` cap (default `10_000`, exposed as `TokenCache.DEFAULT_MAX_ENTRIES` and a read-only `cache.max_entries` property) and evicts the least-recently-used entry on overflow; both `get` and `set` bump the touched key to MRU. Plumbed through `AuthplaneClient.create(cache_max_entries=...)`. Token-exchange cache keys are high-cardinality (the subject token is part of the key), so the cap keeps long-lived clients bounded.
12
+
-`VerifiedClaims.require_scopes(scopes: Iterable[str])` — plural AND-style helper that requires all listed scopes. Empty input is a no-op; on failure the raised `InsufficientScopeError` carries the full requested tuple on `required_scopes` and names every missing scope plus the token's available scopes in the message.
13
+
-`authplane-mcp`: new public surface — `AuthplaneRequestContextMiddleware`, `get_current_request()`, `install_request_context(mcp)` — an ASGI middleware that publishes the active request on a `ContextVar` so the verifier can build a `DPoPRequestContext`.
14
+
-`authplane-fastmcp`, `authplane-mcp`: `AuthplaneTokenVerifier` caches the in-flight verify task per request (keyed by access token on `request.state`), so a repeat `verify_token` within the same HTTP request awaits the same task rather than re-entering the inbound DPoP replay store. Cross-request replay protection is unaffected (distinct requests get distinct caches).
15
+
16
+
### Fixed
17
+
-`authplane-fastmcp`, `authplane-mcp`: inbound DPoP proof-of-possession is now enforced end-to-end. `AuthplaneTokenVerifier.verify_token` forwards a `DPoPRequestContext` (method + reconstructed `htu` + proof header) to `AuthplaneResource.verify`, so `inbound_dpop=InboundDPoPOptions(required=True)` checks the proof on every request. The `htu` origin is always the operator-configured resource URI, never the inbound `Host` / `X-Forwarded-Proto` headers. Operators using `required=True` with `authplane-mcp` should call `install_request_context(mcp)` after constructing `FastMCP` so the verifier can read the per-request context; if it is not installed the request fails closed (401) rather than skipping the check.
18
+
-`authplane-fastmcp`, `authplane-mcp`: DPoP `htu` reconstruction reads `scope["raw_path"]` to preserve percent-encoding (e.g. `%2F`) on the wire under ASGI, falling back to `request.url.path` when the server omits `raw_path`.
19
+
-`authplane-mcp`: `install_request_context(mcp)` is idempotent — repeated calls on the same `FastMCP` instance are no-ops.
20
+
-`require_scope` (singular) now renders an empty token scope set as `(none)` instead of `[]`, matching the plural helper's output. Logging pipelines keyed on the old `Token has scopes: []` string should be updated.
21
+
- Docs and demos now run adapter setup, the async server entry point (`run_streamable_http_async` / `run_async`), and `aclose()` in a single `asyncio.run(main())`, keeping the client's locks, HTTP pool, and background JWKS/metadata refresh tasks on one event loop.
0 commit comments