Released commit: 2371d7a143dbd9f44185d08152c1ddb4fe334ab8
Added
core/resource:WithResourceMetadataURL(string)option andResource.ResourceMetadataURL()accessor point theresource_metadatachallenge parameter at an AS-hosted RFC 9728 document; thehttp,mcpandmark3labsadapters advertise it viaOptions.ResourceMetadataURL.core/resource:AuthErrorResponseWithMetadata(err, resourceMetadataURL, realm...)emits the RFC 9728 §5.1resource_metadataparameter that thehttpadapter used to append itself; the header is byte-identical.core/authplane:ErrAccessDeniedandErrInvalidTargetsentinels for the token-endpoint errorsaccess_denied(403, cross-client exchange not allowlisted on the target Resource) andinvalid_target(400, RFC 8707 §2.2); match witherrors.Is.core/authplane: the auto-wired introspection checker warns once per resource when the AS answersactive: falsefor a locally valid token, pointing at the runtime-client requirement (authserver ≥ 0.1.2).core/resource/verifier: the fail-open revocation branch logs alog/slogwarning carrying the checker error instead of accepting the token silently.http,mcp,mark3labs: every 401WWW-Authenticatechallenge now carriesscope="…"listing the resource's configured scopes (RFC 6750 §3; MCP authorization spec SHOULD), omitted when none are configured. 403 challenges are unchanged.core/resource:AuthErrorResponseVerbose(err error, realm ...string)—AuthErrorResponsewith the error's own message restored in the JSONerror_description. A development aid: it discloses SDK-internal detail to unauthenticated callers, so do not use it in production.
Fixed
core/resource: a resource URI rejected at construction no longer appears unredacted in the error when it carries credentials;errors.As(err, new(*url.Error))keeps working.core/internal/cache: an unknownkidno longer costs one JWKS fetch per verification; forced refreshes have a retry floor ofmin(jwksCacheTTL, 1m). Impact: a newly rotatedkidcan be rejected until that floor elapses.core/internal/cache: a server expiry at or before caching time no longer leaves the document permanently expired, and a server expiry longer than the configured interval is clamped to it.core/resource: the JSON error body for a request with no credentials no longer saysinvalid_request; like the challenge, it now omitserror.
Changed
core/authplane:access_deniedandinvalid_targetno longer count toward the circuit breaker — both are policy answers about the request, not an AS outage.- BREAKING
core/resource:AuthErrorResponseemits a fixederror_descriptionper error code instead of the error's message;RequireScopesno longer lists missing scopes in the body. Migration: thenet/httpadapter logs the diagnostic at DEBUG; logerryourself elsewhere, or useAuthErrorResponseVerbosein development. - BREAKING
core/resource:resource.Newrejects a resource URI with a literal space in the path, a"in the host, userinfo, or a query that is not valid RFC 3986. Migration: percent-encode the offending octets and remove credentials. - BREAKING
core/resource:PRMURL()now keeps the resource identifier's query in the derived PRM URL (RFC 9728 §3);WellKnownPRMPath()is unchanged. Migration: update any hard-coded expectation of the query-less URL.
Deprecated
core/resource/verifier:(*VerifiedClaims).MayAct()— authserver 0.2.0 no longer issuesmay_act; removed in the next minor. Parsing is unchanged until then.