ProtectedResourceMetadata.resource can be serialized with a synthetic trailing slash when a root resource URL is supplied as an already-validated AnyHttpUrl. This changes https://example.com to https://example.com/ and can break strict RFC 9728 resource matching.
Root Cause
AnyHttpUrl normalizes an empty URL path to / before ProtectedResourceMetadata's url_preserve_empty_path model setting can preserve the original spelling. The server auth settings pass an already-validated URL object into the metadata model.
Solution
Normalize only the root path in a ProtectedResourceMetadata pre-validator, removing the synthetic slash before AnyHttpUrl validation. Non-root paths and URL validation remain unchanged.
Changes
Preserve an empty root path for ProtectedResourceMetadata.resource.
Add regression coverage for raw metadata input and an already-normalized URL object.
The public field type remains AnyHttpUrl. Only a root-path slash synthesized by URL normalization is removed; non-root paths, query strings, and validation behavior are unchanged.
Notes for Reviewer
Pyright could not be run with the repository's configured .venv because this incremental worktree does not contain that environment. A separate available environment reported no source-file diagnostics but reported unrelated baseline test typing diagnostics; this is explicitly unverified locally.
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
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.
Problem
ProtectedResourceMetadata.resource can be serialized with a synthetic trailing slash when a root resource URL is supplied as an already-validated AnyHttpUrl. This changes https://example.com to https://example.com/ and can break strict RFC 9728 resource matching.
Root Cause
AnyHttpUrl normalizes an empty URL path to / before ProtectedResourceMetadata's url_preserve_empty_path model setting can preserve the original spelling. The server auth settings pass an already-validated URL object into the metadata model.
Solution
Normalize only the root path in a ProtectedResourceMetadata pre-validator, removing the synthetic slash before AnyHttpUrl validation. Non-root paths and URL validation remain unchanged.
Changes
Testing
Compatibility/Risk
The public field type remains AnyHttpUrl. Only a root-path slash synthesized by URL normalization is removed; non-root paths, query strings, and validation behavior are unchanged.
Notes for Reviewer
Pyright could not be run with the repository's configured .venv because this incremental worktree does not contain that environment. A separate available environment reported no source-file diagnostics but reported unrelated baseline test typing diagnostics; this is explicitly unverified locally.
Linked Issue
Closes #2883