Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.3.0] - 2026-10-01

### Added

- `AccessDeniedException` and `InvalidTargetException` (subtypes of `TokenExchangeException`) for the `access_denied` (403) and `invalid_target` (400) token errors authserver 0.2.0 returns on a non-allowlisted cross-client exchange and on a `resource` that does not match a granted resource exactly; neither counts toward the circuit breaker.
- `ResourceOptions.builder().resourceMetadataUrl(...)`, Spring's `authplane.resource-metadata-url` and `AuthplaneMcpSetup.Builder.resourceMetadataUrl(...)` point the challenge's `resource_metadata` at an AS-hosted RFC 9728 document; `AuthplaneResource.resourceMetadataUrl()` is what adapters advertise. Gated at construction like the resource identifier: absolute `http(s)` with a host, no fragment, no userinfo, and a valid RFC 3986 query.
- `AccessDeniedException` (403) and `InvalidTargetException` (400), subtypes of `TokenExchangeException`, for the `access_denied` and `invalid_target` errors authserver 0.2.0 returns on token exchange; neither counts toward the circuit breaker.
- `ResourceOptions.builder().resourceMetadataUrl(...)`, Spring's `authplane.resource-metadata-url` and `AuthplaneMcpSetup.Builder.resourceMetadataUrl(...)` point the `resource_metadata` challenge at an AS-hosted RFC 9728 document; validated at construction.
- New `WwwAuthenticate.descriptionFor(errorCode)` and `FALLBACK_ERROR_DESCRIPTION`, plus `verboseDescription` overloads on `WwwAuthenticate.of(...)` and `FailureResponse.of(...)` that restore the exception message for local debugging.

### Changed

- **BREAKING** `WwwAuthenticate.of(...)` and `FailureResponse.of(...)` now emit a fixed `error_description` chosen by the `error` code — on the challenge and in the JSON body alike — instead of the exception message. **Migration**: log `getMessage()` server-side, or pass `verboseDescription: true`.
- **BREAKING** The `ServerTransportSecurityException` the `mcp` and `spring` adapters raise now carries the fixed per-code sentence, not the exception message, which the MCP SDK's transport renders into the response. `extract(...)` still throws the typed exception with its own message.
- **BREAKING** `AuthplaneAuthenticationProvider` no longer reflects the exception message into the `OAuth2AuthenticationException` it raises; both the `OAuth2Error` description and the exception message now carry the fixed per-code sentence. The SDK's own entry point discarded both, but an application wiring this provider under Spring's `oauth2ResourceServer` gets `BearerTokenAuthenticationEntryPoint`, which renders the description straight into `error_description` — and `server.error.include-message=always` put the message in the error body. **Migration:** read `getCause()` for the original exception, which is unchanged.
- **BREAKING** `AuthplaneAuthenticationProvider` puts the fixed per-code sentence, not the exception message, into the `OAuth2AuthenticationException` it raises, which Spring's `BearerTokenAuthenticationEntryPoint` renders on the wire. **Migration:** read `getCause()` for the original exception.
- **BREAKING** `ASCredentials` now rejects a blank `clientSecret` at construction: authserver ≥ 0.1.2 answers `active: false` to unauthenticated introspection, so a public client would silently reject every token as revoked. Register a confidential client and pass its secret.
- The built-in introspection checker warns at construction when the client has no `AuthProvider`, and once per checker when the AS answers `active: false` for a token that passed local verification, pointing at the runtime-client requirement (`authserver admin resource runtime-client add`).
- **BREAKING** A resource identifier must now name a host at construction, not just carry a scheme: `urn:example:api`, `https:///mcp` and `https://:8443/mcp` are rejected by the new `ProtectedResourceMetadata.requireAuthority(String)` gate, which every construction path calls. An opaque identifier bound every DPoP request to the literal origin `urn://null`. **Migration:** configure the absolute URL clients address, e.g. `https://api.example.com/mcp`.
- **BREAKING** A resource identifier must name a host: `urn:example:api`, `https:///mcp` and `https://:8443/mcp` are rejected at construction. **Migration:** configure the absolute URL clients use, e.g. `https://api.example.com/mcp`.
- `DocumentCache.forceRefresh()` now waits for a refresh already in flight instead of returning the document it holds as 0.2.0 did — its caller reaches it precisely because that document lacks the `kid`.
- Documentation correction for 0.2.0: `DocumentCache`'s constructor has refused a non-positive refresh interval and a null clock since that release — both reached the same permanent-expiry state the 0.2.0 cache-directive fix closed — and the published 0.2.0 notes never recorded it. An embedder constructing `JwksCache` or `MetadataCache` directly with a refresh interval of `0` upgrades from 0.1.0 and gets an `IllegalArgumentException` at construction with nothing in the changelog explaining it.

### Deprecated

Expand Down
Loading