oauth-v2-1
oauth-v2-1 copied to clipboard
Phishing/Audience Mix-Up Mitigation for Resources
A client currently has no way to detect whether an authorization server supports the RFC 8707 Resource Indicators for OAuth 2.0 extension. An authorization server that implements support for RFC 8707 would process a requested resource and audience-restrict the issued access token if the resource was valid or return an invalid_target error code if the requested resource is not valid for the authorization server. If the authorization server doesn't support RFC 8707 it would silently ignore the resource parameter and issue an access token to its default audience for the request (e.g client+scopes requested).
Since the access_token in the token response is opaque to the client, the client has no way to know the value of the issued token's audience. This is especially problematic when using metadata to dynamically discover an authorization server such as with OAuth 2.0 Protected Resource Metadata (RFC 9728).
For example resource.example could publish https://resource.example as the resource identifier but specify https://accounts.google.com/o/oauth2/v2/auth as the authorization server as a phishing attack. A client would then attempt to obtain an access token from the specified authorization server with the dynamically discovered resource
https://accounts.google.com/o/oauth2/v2/auth?client_id=...&scope=...&resource=https://resource.example.
If the authorization doesn't support RFC 8707 then it would just process this as a normal authorization request, ignore the invalid resource, and issue a default access token (assuming user consented). This is the exact scenario that Model Context Protocol (MCP) project is vulnerable to which has taken a dependency on OAuth 2.1
While this security risk is explicitly called out in the security considerations of RFC 9728, the interoperability gap still exists for an OAuth 2.1.
Secure determination of appropriate authorization servers to use with a protected resource for all use cases is out of scope for this specification. This specification assumes that the client has a means of determining appropriate authorization servers to use with a protected resource and that the client is using the correct metadata for each protected resource. Implementers need to be aware that if an inappropriate authorization server is used by the client, an attacker may be able to act as an adversary-in-the-middle proxy to a valid authorization server without it being detected by the authorization server or the client.
If OAuth 2.1 included the RFC 8707 Resource Indicators for OAuth 2.0 extension, clients could expect an authorization server to process the resource or return invalid_target error code. This would help projects like MCP mitigate risks of using metadata based discovery. An authorization doesn't need to support resource indicators to be complaint. It just needs to return invalid_target if a resource is specified. . This is small lift for an authorization (support an error code) has a ton a value for dynamic discovery scenarios.
Alternatively, OAuth 2.1 could specify a new token response field for audience. This would push validation to the client to ensure the that issued token was for an audience it wanted and prevent forwarding a token to a resource server with a mismatched audience. Since audience doesn't need to be 1:1 to a resource's url this is problematic but could be profiled.
We are currently implementing SDKs at @keycardlabs which ensure that MCP clients can securely access MCP servers protected by OAuth 2.0, where both the MCP server and OAuth authorization server are dynamically discovered by the MCP client. This discovery is happening via OAuth 2.0 Protected Resource Metadata (RFC 9728) and OAuth 2.0 Authorization Server Metadata (RFC 8414), per the current draft of MCP authorization.
It is clear that confused deputy/mix-up vulnerabilities are inherent today, wherein MCP clients will present access tokens obtained from any OAuth authorization server chosen by the MCP server - even in cases where MCP server is not the intended audience. This, in turn, allows the MCP server to access resources using that access token, even though it has not been authorized to do so.
In order to fully secure these dynamic discover flows, I'm currently of the opinion that the client needs to take an active role in validating where it sends tokens to (as noted @mcguinness's last paragraph). What I would expect is a flow such as:
- MCP/OAuth client makes a protected resource request, receives a 401 challenge with
resource_metadataparameter, per section 5.1 of RFC 9728. - MCP/OAuth client fetches protected resource metadata, and obtains resource identifier from
resourceparameter and authorization server issuer identifiers fromauthorization_serversparameter. - MCP/OAuth client fetches authorization server metadata.
- MCP/OAuth client makes an authorization request, including a
resourceparameter set to the resource identifier obtained in step 2, per section 2.1 of RFC 8707. - Authorization server processes the authorization request and, if authorized, issues an authorization code.
- MCP/OAuth client exchanges the authorization code for access token
- Authorization server includes (new)
resourceparameter in token response. - MCP/OAuth client verifies that
resourceparameter in token response matches the resource identifier obtained from metadata in step 2. - Assuming verification passes in step 8, MCP/OAuth client uses access token to make protected resource request.
Note that this flow works in any dynamic scenario involving API access. For instance, its equally applicable to HTTP or REST APIs. I'm just using MCP for illustrative purposes as it is currently in focus.
- Authorization server includes (new)
resourceparameter in token response.
@jaredhanson I was expecting this as well. Unfortunately we may need to draft a net new extension for this based on my chat with @aaronpk. Its a big miss that this wasn't included in RFC 8707. I was also surprised this also wasn't included in RFC 9700 Best Current Practice for OAuth 2.0 Security and may need to go into the next revision
It is clear that confused deputy/mix-up vulnerabilities are inherent today, wherein MCP clients will present access tokens obtained from any OAuth authorization server chosen by the MCP server - even in cases where MCP server is not the intended audience.
Currently, a fix is to make sure you are getting a proof-of-possesion token. This assumes that proof-of-possesion tokens are properly supported by the ASs and RSs (and the client), though.
See for example, a related attack in the UMA protocol.
- Authorization server includes (new)
resourceparameter in token response.@jaredhanson I was expecting this as well. Unfortunately we may need to draft a net new extension for this based on my chat with @aaronpk. Its a big miss that this wasn't included in RFC 8707. I was also surprised this also wasn't included in RFC 9700 Best Current Practice for OAuth 2.0 Security and may need to go into the next revision
If I understand correctly, the recommendation not to rely on client-side resource parameter matching in the access token response is discussed in RFC9700 Section 4.10.3. Instead, enforcement mechanisms on resource server-side, such as audience-restriction, are currently recommended.
I don't think returning invalid_target is enough, because RFC 8707 Resource Indicators for OAuth 2.0 says that the resource parameter represents an identity which MAY equal a locator. (implying that it may also be totally undelated)
Sure, in places I have seen where the AS treats the resource parameter as an abstract identifier, I have also seen recommendations to use an URI scheme that is not confusable, e.g. using api://my-resource-identity instead of https://my-resource-identity/, but I would not count on that always happening, especially since RFC 8707 itself does not have any recommendation on that.
I never understood why RFC 9728 OAuth 2.0 Protected Resource Metadata lists both client and AS as potential users. I can see how an AS might use it, but for a client to use RFC 9728 it must know where the AS intended the access token to be used, and I am not aware of any machine readable way for the client to discover where it is safe to use an access token.
- Client should know whether a given Authorization Server supports resource-based authorization or token requests
- Client should know what the outcome of a resource indicator token request and not guess based on absence of error code . This is useful not only for client-side security but also caching purposes. Clients may want to store tokens in a cooke-jar like fashion for multiple resources
- RS should require proof-of-possession tokens such as DPOP to ensure intermediates can't replay tokens
The scenario that is of concern for projects like MCP is that a RS may publish an Authorization Server that it wants to phish a token from and that Authorization Server (e.g. accounts.google.com) or its protected resources may not require proof-of-possession (e.g Google APIs). If the API that the attackers wants to use doesn't require possession then there are not mechanisms for a client-side enforcement/defense when using resource based requests.
I am going to write up a draft for a token response param and will see what folks think.
A new draft was published that defines the resource token response parameter https://datatracker.ietf.org/doc/draft-mcguinness-oauth-resource-token-resp/
A new draft was published that defines the
resourcetoken response parameter https://datatracker.ietf.org/doc/draft-mcguinness-oauth-resource-token-resp/
Nice. I think it would be good to add wildcard/URL pattern support. Many AS/RS reuse the same access tokens for multiple resource URLs, e,g. a RS may accept the same access token on https://resource.example.com/users/1, https://resource.example.com/users/2, https://resource.example.com/users/3 etc, so the resource response parameter could be a pattern like https://resource.example.com/users/* or https://resource.example.com/*
Also the Security Considerations section could have some more detail. For example say that if the parameter is missing from the response, the client should only use the access token if it knows what policy the AS has on where the access token can be used.
Many AS/RS reuse the same access tokens for multiple resource URLs
This is about the resource server identifier, not individual resource URLs.
Ah, then I misunderstood. Then I don't see what this is for. If the client still have to know the AS policy of which resource URLs map to a given resource server identifier, then the client could just as well know the AS policy of which resource URLs map to a given set of token request parameters.