What is the purpose of OAuth 2.0 redirect_uri checking?
The OAuth 2.0 specification's authorization code mechanism includes redirect URI checking from the site you redirect to. See steps D and E in section 4.1 of the spec. Also, section 4.1.3 describes in detail that the redirected-to client needs to transmit
redirect_uri, and that it needs to match that of the initial authorization request.
I can't think of any attack vector that is mitigated by this being a part of the protocol. Why is this redirect_uri check necessary?
By not validating the
redirect_urian OAuth provider can be used as an ideal phishing vector. The
redirect_uriis an address used by OAuth providers as a location to deliver the
access_tokenby means of a browser redirect. The popular OAuth provider Facebook has run into many vulnerabilities relating to OAuth redirection.
In this attack, the attacker presents the victim with a URL to an authentication portal that the victim trusts (like Facebook), and by using this authentication portal the victim's secret access token is delivered to an HTTP server controlled by the attacker.
Authentication is about intention, tricking a user into allowing access to an unintended resource is a vulnerability.
But the redirection_uri in the Access Token Request (section 4.1.3 in the spec) mentioned by Steven Xu is only checked on the Authorization Server, the access_token is not redirected to this uri. So the code and the redirection_uri is checked before the access_token is returned to the client app... Me too, I can't think of a reason for the additional checking of the redirection_uri...
Is it necessary to pass the redirect_uri when being authorized if the client provided it during the registration process?
@pfust75 The check is only useful if the `redirect_uri` wasn't checked in the first step. Say Alice clicks a link like `https://oauth.example.com/login?client_id=123456&redirect_uri=evilsite.com%2Fpwned`. This request will not be rejected *unless* oauth.example.com requires clients to register a `redirect_uri`. Let's say that's not the case, then evilsite.com (Mallory) receives the auth code. It can then forge this URL `https://client123456.example.com/oauth_redirect?code=987654321`, and Mallory will have gained access to Alice's account
Edited based on comments. I previously thought the OP was referring to redirect_uri validation during the authorization request, and linked to an example of an attack here. I've updated the answer below.
TL;DR: If a static redirect URL is required to be registered and is strictly matched by the provider, I do not believe that the redirect_uri would be required during the access token request.
The registration requirements (184.108.40.206) indicate that the redirect URI should be registered. However, not all providers perform exact matches of the redirect URI, although the spec requires it. The OAuth spec attempts multiple countermeasures to guard against these possibilities, with the redirect_uri <-> authorization code binding requirement described in the Threat Model and Security Considersations RFC (220.127.116.11).
For example, GitHub matched URL prefixes, which lead to the attack described here by Egor Homakov. In particular, Bugs 1 and 2 allowed an attacker to use a white-listed redirect URI to obtain a code, and then use that code to complete the callback flow and gain access to the victim's account. In this case, the client (Gist), sent the right redirect URI to the provider (GitHub), and GitHub would have not granted the access token if it had checked to ensure the redirect URI was the same one used during the authorization request:
It was flawed: no matter what redirect_uri the Client sent to get a token, the Provider responded with valid access_token.
The attacker could hijack the authorization code issued for a "leaky" redirect_uri, then apply the leaked code on real Client's callback to log in Victim's account.
To summarize, the redirect_uri is required when obtaining an access token to ensure that a leaked code from a redirect to a page the attacker can insert code in doesn't immediately compromise the OAuth flow. A more complete overview of the attack vector is described here by Egor as well:
The attack is straightforward: find a leaking page on the client's domain, insert cross domain image or a link to your website, then use this page as redirect_uri. When your victim will load crafted URL it will send him to leaking_page?code=CODE and victim's user-agent will expose the code in the Referrer header.
Now you can re-use leaked authorization code on the actual redirect_uri to log in the victim account.
Remediation: flexible redirect_uri is a bad practise. But if you need it, store redirect_uri for every code you issue and verify it on access_token creation.
How is this situation possible if the Registration Requirements are followed? Mainly that: _"The authorization server SHOULD require all clients to register their redirection endpoint prior to utilizing the authorization endpoint."_ The victim could never be redirected to the evil site.
As Egor said, link 1:
all oauth exploits are based on tampering with the redirect_uri parameter.
and link 2:
Vector 2. If spec was implemented properly then tampering redirect_uri to other, "leaky", values is pointless. Because to obtain access token you must send redirect_uri value with client creds. If actual redirect_uri was "leaky" and not equal real redirect_uri Client will not be able to obtain access_token for this code.
redirect_uriis the callback for the Client to receive the
Authorization Code. The Client treats anyone who brings the code as the Resource Owner.
Attacker may replace the
redirect_uriwith a malicious one in Step A to get the code. Then he can rebuild and trigger the uri to hijack the session belongs to the Resource Owner.
However, every code have a corresponding
redirect_uriit was issued for, i.e., code will be calculated based on the polluted
redirect_uriin Step C.
Note that the request in Step D is made by the Client. It will always use the right form of
redirect_uri. Finally, Authorization Server turns out the code does not match the uri, therefor no token will be responded back in Step E.