I started looking at OAuth - Google's and Facebook's implementation. Both of the implementations, in the authorisation flow, seem to send the "Authorization code" back to the web browser. I was wondering what is the benefit of sending the code to the browser vs just hitting the redirect_uri from the authorisation server? If we send code to the browser we risk that someone somehow gets hold of it while the risk does not exist if the code is sent straight to the server (redirect uri target).
2 Answers
The delivery of the Authorization Code is not more a security issue than is sending the user's password from the browser to the facebook server (for example). That means, if there is an insecure connection, an attacker would be able to compromise the user's authentication anyway. For that reason, OAuth is meant to be executed with HTTPS.
The reason why it needs to be implemented like that is because only this way the OAuth client is able to identify the user who requested OAuth. This is because when a user for example clicks on the facebook button on StackOverflow, it immediately connects him to facebook where the OAuth process starts. StackOverflow so far doesn't know that this user requested OAuth via facebook. Only through now redirecting the user to StackOverflow along with the Auth Code does StackOverflow know that this user (with his session ID) used facebook OAuth and got this Auth Code. Now StackOverflow is able to connect Session ID with Auth Code and knows who requested facebook's OAuth.
edit I've looked at the RFC of OAuth, and I have to make a correction regarding my first point. While it is highly recommended for the redirect endpoint to use HTTPS, it is not mandatory yet. See Endpoint Request Confidentiality. So the Auth Code indeed might be sent unencrypted at some point, that is when redirecting to the original server which has not HTTPS activated. But still, to me this is a huge security issue with the whole OAuth process. HTTPS should imo be mandatory. If a server can't HTTPS it's connection, it shouldn't play with OAuth after all.
-
I don't agree with the first point but the one about tracking every user's state is really good point. That seems to fit very well why code is not delivered to the server part of the client but to the user agent part. Aug 26, 2014 at 10:14
-
1Well, to me it doesn't make sense to focus on the Authorization Code getting compromised, when at the same time the user is sending his password (or his session id via a cookie, depends on if he already was logged in). If the connection is not secure, then you're right, it's unsafe to send the Authorization Code. But then the whole OAuth flow is flawed and not only the Auth Code gets stolen, but also the user's password. On the other hand, if the connection is secure, then both the password and the Auth Code can be sent from client to server and vice versa. Aug 26, 2014 at 11:16
-
The thing is that the OAuth provider will use TLS while the some websites/webapps still use plain old HTTP. I feel safe logging in to Google but I don't usually feel safe sending my password to some random website. Aug 26, 2014 at 11:26
-
-
@PhilippMurry Principal reason is to protect the client (ex. Stack Overflow) against evil site impersonating User (ex. Browser). The redirect is the only way for the client to guarantee that the user that authenticate with the provider is really the same user that ask for the authorization request. Aug 26, 2014 at 14:19
It's sent back to the browser because it is essential to do it this way.
It might be crazy, but the whole OAuth/OpenId security is based on the fact that your browser will do the right redirect.
Let's look at an attack if you don't use the browser as a redirect but first let's define a simplified version of the OAuth "framework" for our example.
- Client : The application you wish to connect to
- Browser : Your browser...
- Provider : The OAuth provider (Ex.: Google or Facebook)
- Evil : The attacker.
The normal flow
- Browser ask client to login
- Client redirect browser to Provider
- Provider authenticate browser then redirect to Client with token
- Client communicate with Provider giving the token for authorization.
- Client grant authorization to browser.
Your flow
- Browser ask client to login
- Client redirect browser to Provider
- Provider authenticate browser and send token to client giving him authorization
- Client grant authorization to browser
The problem here is that the client is not sure that the browser it is communicating with is the same browser that authenticate himself with provider.
An attack on your flow
- Browser access Evil for some bad reason
- Evil impersonate Browser and ask Client to log in.
- Client send redirect link to Evil
- Evil forward the link to Browser which redirect him to Provider
- Provider authenticate browser and send token to Client giving him authorization
- Client grant authorization to Evil thinking it is Browser
See the problem in the last step?
This would not have happen if you were using a browser redirect to send the token to the client. By using a browser redirect, you make sure that the Browser that is authenticating with Provider is the same Browser that is trying to gain authorize right with Client.
This is a crucial step. Especially since many Provider will send the token automatically after the first time if you are log in. So, Evil could gain access to your account just from you visiting his page and you would not even know.
The same attack with normal flow
- Browser access Evil for some bad reason
- Evil impersonate Browser and ask Client to log in.
- Client send redirect link to Evil
- Evil forward the link to Browser which redirect him to Provider
- Provider authenticate browser then redirect to Client with token
- Client communicate with Provider giving the token for authorization.
- Client grant authorization to browser.
Here evil was eclipsed at the end because of the redirect. This is why the protocols do so many checks on the redirect url to make sure it will not redirect to a malicious site stealing the authorization token.
OAuth/OpenId protects you again phishing attempt. But they can only do it because your browser is doing the right redirect. On desktop/mobile app this is not really working, hence why the protocols are less secure on desktop/mobile app.
Specifically, it protects the Client against phishing attempt. The client must make the very hard decision : Is the browser asking for authorization the same as the browser that authenticate with the provider? And the only thing helping the client to do that, is the redirect and the fact that your browser is secure.
Since it directly protects the Client against phishing, it indirectly protects you.
-
Actually I'm not sure if I understand the section "An attack on your flow". In step 2 is the Evil a fake provider or redirects client to authentic provider? Where does the redirect link come from? why would a provider accept some random token in step 4 if it was not invloved in the exchange previously? Aug 26, 2014 at 12:40
-
@markovuksanovic Evil is faking Client to Browser and Browser to Client. Client try to redirect Evil to the provider thinking it is browser. Evil then forward that redirect to Browser as it can't authenticate himself with Provider, but Browser can. In the last step, since Client think that Evil is Browser, it will grant authorization to Evil instead of Browser. Aug 26, 2014 at 12:48
-
@markovuksanovic To answer specifically your questions. Evil is redirecting Browser to the real Provider. It is in fact a real authorization request that is sent to provider as it was created by client, forward to evil, forward to browser and then receive by Provider. Aug 26, 2014 at 14:22
-
Actually, I'm not really clear how this would work. The idea of sending code directly to redirect uri is to not have to deal with possibly compromised user-agent. If the authorisation server sent code to "Evil" that would mean that it does not hit redirect uri directly but indirectly. I need to think a bit more but I'm not convinced that this explanation holds. Aug 27, 2014 at 1:15
-
@markovuksanovic With your flow, the authorization token is sent directly to the Client. But then, Client doesn't know to who it should give the authorization access. Since it's Evil that contacted Client, Client will give access to Evil instead of giving access to Browser. THat's the problem and it does not happen if you use the Browser (user-agent) to do the redirect. Aug 27, 2014 at 3:02