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
{{ message }}
Repository navigation
[Client] Close the remaining OAuth and redirect gaps before 0.10.0 - #727
refuse an authorization server or endpoint in a private network (e.g. 169.254.169.254) that a remote server names, unless setExpectedIssuer() allows it
turn off redirects on a Symfony client passed to HttpTransport without auth, and name the HTTPlug clients that still follow them in the docs
note in the changelog what a redirect exposed before 0.10.0
a protected resource document for another resource no longer stops the next location
refresh a token shortly before it expires instead of waiting for the 401
a pending authorization on SSE resumption and a failing tell()/seek() no longer end up as transport or stream errors
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Stored-token authentication can abort on unguarded registration-read failures, and metadata validation rejects private-network token endpoints even when their issuer is explicitly trusted.
No open issues 🎉
2 previously missed issues
In code that hasn't changed since last review
Allow trusted issuers to opt into private-network token endpoints
The setExpectedIssuer() opt-in described in the PR and authorization guide cannot allow a trusted issuer such as https://auth.example.com whose token endpoint is https://10.0.0.5/token: this check unconditionally rejects the metadata before discovery can apply that setting. Carry the explicitly trusted issuer through endpoint validation so callers can opt into this private-network deployment while retaining rejection by default.
Guard client registration lookup and preserve token fallback
src/Client/Auth/OAuthAuthenticator.php:491
When a stored token is reused, $this->client is null, so this lookup reads the credential backend before entering the try block. If getClientRegistration() throws Mcp\Exception\RuntimeException, authenticate() aborts instead of sending the still-valid token; move the lookup inside the guarded block so the refresh fallback also covers registration-read failures.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Dynamically registered clients still share a token key, allowing one registration’s token to be reused or refreshed with another’s credentials.
No open issues 🎉
1 previously missed issue
In code that hasn't changed since last review
Key tokens by the actual dynamically registered client ID
src/Client/Auth/OAuthAuthenticator.php:826
Dynamically registered clients still share a token key because neither configuration field contains their assigned client ID. When a deferred flow for registration A completes after registration B replaces it, a later authenticator can reuse A's token and attempt to refresh it with B's credentials. Include the actual registration's client ID in the key and use that identity consistently for token lookup, refresh and deferred completion.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Human assessment is needed for a short-lived-token edge case that can trigger unnecessary refreshes before every request, adding overhead and risking token-endpoint rate limits.
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
authIssues and PRs related to Authentication / OAuthbreaking changeBreaking the Backwards Compatibility PromiseClientIssues & PRs related to the Client component
2 participants
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.
Follow-up to #669 and #660 before tagging 0.10.0 - one commit per point:
AccessTokenthe client it was issued to - options b) and c) of [Client] Key stored OAuth tokens by client, not only by issuer and resource #719, soCredentialStorageInterfacestays as it is and a replaced dynamic registration can't hand its token to the next one169.254.169.254) that a remote server names, unlesssetExpectedIssuer()allows itHttpTransportwithout auth, and name the HTTPlug clients that still follow them in the docs401tell()/seek()no longer end up as transport or stream errorsbbdu3as@authorof the classes from [Client] Support completing OAuth authorization in a later request #660Closes #719