# OAuth2: Why should we validate the `redirect_uri` when exchanging the authorization code for an access token?

> Beware, technical article ahead!

OAuth 2 and OpenID are complex protocols. It's full of tiny details that are there for the sake of security and it's not always clear why some checks are necessary. This article is about such a detail.

## Prelude

Before stating what is missing, let us briefly look at how the OAuth2 "exchange" takes place.

1. First is the authorization request which redirects the user to the provider:
    

```http
GET /authorize
    ?response_type=code
    &client_id=...
    &redirect_uri=https%3A%2F%2Fexample.org%2Fcallback
    &...
```

1. Once the user grants the scope, the callback is invoked with the *authorization* *code*. The server provided in the `redirect_uri` receives this code as follows.
    

```http
https://example.org/callback
?code=Qcb0Orv1zh30vL1MPRsbm&...
```

1. Now, at *example.org*'s server side, the *authorization code* (which is basically a nonce) is exchanged for the "real" *access token*. The URL to exchange the authorization code for a token looks like this:
    

```http
POST /token
?grant_type=authorization_code
&code=Qcb0Orv1zh30vL1MPRsbm
&redirect_uri=https%3A%2F%2Fexample.org%2Fcallback
```

Some parameters were omitted for brevity's sake, but it's sufficient for the upcoming explanation.

## Why is the \`redirect\_uri\` sent again?

Sending the `redirect_uri` in the first step is obvious, it's to know where the authorization code should be sent to via redirect.

However, when exchanging the authorization code for a token, why send it again?

Let's assume an attacker manages to manipulate the `redirect_uri` of a victim. Let's also assume this manipulated redirect is accepted by the provider for whatever reason. The attack pattern may look like this:

1. The attacker achieves to manipulate the URI in the first step as follows `/authorize?...&redirect_uri=https://attacker.xyz/callback`
    
2. The attacker receives the authorization code `https://attacker.xyz/callback?code=...`
    
3. The attacker can now invoke `/token?code=...&redirect_uri=https://attacker.xyz/callback` or `/token?code=...&redirect_uri=https://example.org/callback` as it please.
    

It makes no difference since the attacker is in full control of what is sent as `redirect_uri` ...right?

Anyway, it's probably further protected by a client secret or PKCE. Is there a way around it?!

## Here comes the trick!

Let's assume *Alice* is the attacker and *Vincent* the victim.

Both *Alice* and *Vincent* have an account at *example.org*, which can for example use google photos to make collages of your family pictures.

Somehow Alice manages to manipulate the redirect\_uri of Vincent, redirecting him to `https://attacker.xyz/callback?code=ABC...`

This attacker's website will probably also discreetly redirect back to example.org after grabbing the code. Vincent won't see example.org working properly, probably saying something went wrong, without suspecting anything bad.

On the other hand, Alice could go to example.org and use Vincent's code to complete the OAuth2 flow for herself, simply by pasting `https://example.org/callback?code=ABC...`

In other words, Alice will be able to impersonate Bob and make photo collages of Vincent's family.

This is of course just an example to illustrate the issue, but you certainly see the extent of this kind of exploit, which lets the attacker impersonate someone else.

Verifying the `redirect_uri` is there to prevent such "code stealing". It ensures such a triangle with an attacker in the middle did not take place by verifying that the code was indeed sent to the place the client app expected. Nothing more, nothing less.

## How likely is it to have a valid attacker `redirect_uri`?

This cannot happen if a single `redirect_uri` is defined. It happens in scenarios where multiple callback URIs are defined (or if the server check is missing!) or where some loose matching takes place. Imagine for example a service which lets developers host their own apps behind a subdomain, providing authentication as a convenience. This could lead to a legitimate app goodapp.example.org being manipulated to leak the code to badapp.example.org, which might have a legitimate `redirect_uri` for example.org too. This could also be a larger organization, where some isolated app was hacked, and so on.
