49

Using oAuth 2.0, in "authorization-code" Authorization Grant, I first call to "/authorize", get the code, and then use this code within a call to "/token" to get the access-token.

My question: why this is the flow? I guess it is from a security reason, but I cannot figure it out. Why the implementation is this way, and not getting the access-token immediately after the first call ("/authorize")?

Why do we need this code for?

OhadR
  • 8,276
  • 3
  • 47
  • 53
  • 1
    http://stackoverflow.com/questions/13387698/why-is-there-an-authorization-code-flow-in-oauth2-when-implicit-flow-works-s – Muhammad Umer May 24 '16 at 20:02
  • Possible duplicate of [Why is there an "Authorization Code" flow in OAuth2 when "Implicit" flow works so well?](https://stackoverflow.com/questions/13387698/why-is-there-an-authorization-code-flow-in-oauth2-when-implicit-flow-works-s) – Ilya Serbis Jul 29 '19 at 23:14
  • This Q/A is a text book example for the infamous X/Y problem here on SO ... what is so difficult about carefully reading a question and answering that question and not some other more convenient one?! – Raffael Jul 10 '20 at 12:02

6 Answers6

23

Could it also be that by having this intermediate step prevents the client from seeing the access token?

From O'Reilly book:

Authorization code This grant type is most appropriate for server-side web applications. After the resource owner has authorized access to their data, they are redirected back to the web application with an authorization code as a query parameter in the URL. This code must be exchanged for an access token by the client application. This exchange is done server-to-server and requires both the client_id and client_secret, preventing even the resource owner from obtaining the access token. This grant type also allows for long-lived access to an API by using refresh tokens.

Implicit grant for browser-based client-side applications The implicit grant is the most simplistic of all flows, and is optimized for client-side web applications running in a browser. The resource owner grants access to the application, and a new access token is immediately minted and passed back to the application using a #hash fragment in the URL. The application can immediately extract the access token from the hash fragment (using JavaScript) and make API requests. This grant type does not require the intermediary “authorization code,” but it also doesn’t make available refresh tokens for long-lived access.

UPDATE - yes indeed:

When Should the Authorization Code Flow Be Used? The Authorization Code flow should be used when

  • Long-lived access is required.

  • The OAuth client is a web application server.

  • Accountability for API calls is very important and the OAuth token shouldn’t be leaked to the browser, where the user may have access to it.

More:

Perhaps most importantly—because the access token is never sent through the browser— there is less risk that the access token will be leaked to malicious code through browser history, referer headers, JavaScript, and the like.

Community
  • 1
  • 1
davidhq
  • 4,660
  • 6
  • 30
  • 40
  • 1
    So Main point is that Access Token is not given in Callback Url is to not have it exposed on client side ever in any form. Why? it's SSL. Only reasons i can think of are to prevent some malware from accessing url and then have life time access to user data as much as the app user authorized. – Muhammad Umer May 24 '16 at 19:53
  • 1
    But why not have api work with server_secret_key + authorization_code. Instead of access_token only. This way there wont be risk by authorization code stolen as server still has secret key that malware wont have – Muhammad Umer May 24 '16 at 19:55
  • 1
    @MuhammadUmer Did you get any satisfactory explanation of this? I am also looking for same info. – Kiran Machhewar Mar 18 '19 at 00:18
  • 1
    no i didn't, now i dont even remember what i was thinking – Muhammad Umer Mar 18 '19 at 17:45
  • 1
    @MuhammadUmer If I understand you right, the server_secret_key + authorization_code way you suggest is identical to the Access Token Request step of the Authorization Code Grant workflow: your app on server exchanges its client_secret + authorization_code (received after first step) for the token. And then it uses this token to access to API. – Ilya Serbis Jul 29 '19 at 13:05
  • What's the rationale for authorization codes being used when long-lived access is required? How does the authorization code influence the access token's longevity? – Leeren Aug 10 '19 at 22:25
11

The authorization code flow is meant for scenarios where 3 parties are involved.

These parties are:

  • Client

    The user with his web browser. He wants to use your application.

  • Provider

    Has information about the user. If somebody wants to access this data, the user has to agree first.

  • Your (web) application

    Wants to access information about the user from the provider.

Now your app says to the user (redirecting his browser to the /authorize endpoint):

Hey user, here is my client id. Please talk to the provider and grant him to talk to me directly.

So the user talks to the provider (requests the authorization code and returns it to your app by opening your callback URL in his browser):

Hey provider, I want to use this app, so they require to access my data. Give me some code and I give this code to the application.

Now your app has the authorization code which is already known by client AND the provider. By handing this over to the provider your app can now prove, that it was allowed by the client to access his data. The provider now issues your (web) app an access token, so your (web) app won't have to redo these steps each time (at least for a while).

In case of other application types where your app is running directly at the client side (such as iPhone/Android apps or Javascript clients), the intermediate step is redundant.

arcseldon
  • 35,523
  • 17
  • 121
  • 125
Jan Gerlinger
  • 7,361
  • 1
  • 44
  • 52
  • 25
    Why not give the user the access/refresh token right off the bat? Why is there is intermediate step with the code? – user2316667 Oct 05 '14 at 21:39
  • 19
    Agreed, this doesn't answer the question. The question is *why*. – stickfigure Apr 14 '15 at 22:14
  • 2
    @stickfigure can you please check my answer and see if it clears your doubt. If not then please let me know. – ksht Sep 24 '15 at 18:43
  • 3
    Hey Jan, in Oauth speak, Client is the web app, resource owner is the "user", provider could be federation provider ,or Identity Provider. Liked your description but found the "party" names slightly confusing. – arcseldon Mar 26 '16 at 09:48
  • Yes. The terminology here was meant for someone coming from a traditional `client/user <-> server/web app` background who wants to connect his app with a data provider (e.g. Google). – Jan Gerlinger Mar 29 '16 at 14:02
  • Detailed answer can be found here https://stackoverflow.com/a/16341985/1514431 – ndh103 Feb 17 '21 at 14:21
  • a bit confused with this answer.. can you keep using the terms, such as user/client, you/I, consistently? – ChrisZ Jul 25 '21 at 05:35
9

Data on client side is generally considered unsafe. In the case of implicit calls where token is granted in the initial step itself, anyone with the access_token can request for data, the API doesn't know who is calling that API.

But, in the case of web-server apps where the application wants to identify itself, client_id with client_secret is sent along with authorization_code to get access_token, which in future can be sent independently.

Suppose, if access_token is granted initially itself then as client_id and access_token will still be considered exposed, so the app will have to send client_secret in addition to access_token every time to assure that request is really coming from it.

While in the current scenario, after getting access_token, further requests can be made independently without needing client_secret.

ksht
  • 159
  • 1
  • 7
2

One important point is

Perhaps most importantly—because the access token is never sent through the browser— there is less risk that the access token will be leaked to malicious code through browser history, referer headers, JavaScript, and the like.

Fizer Khan
  • 88,237
  • 28
  • 143
  • 153
  • But in facebook Oauth, the access token is passed to browser [link](https://developers.facebook.com/docs/facebook-login/web#token) – Qiang Jan 22 '16 at 23:09
2

I think it is like this;

When we use the authorization code, we have 2 verification parts;

  • 1; to verify ownership of the user, because he logs in
  • 2; we know that the client, is really who he says he is because the client is sending his client_secret.

So if we would return the access token on the moment when the user authenticates instead of the authorization code, we know that it is the user requesting it but we dont know that it will be used for the registered client. So for example your webapp.

When we use the 'implicit grant'; (or return the access token instead of authorization code)

  • 1; We know it is the user who is receiving the access token, but there is no need in getting a authorization code because the 'user-agent' based application is not checkable. It is checkable, if you think about it but it is usable for everyone. The client_secret is publicly viewable in the source code of the 'user-agent' based application so everyone can just 'view source code' and copy the client_secret and use this method to verify ownership of the client.
Nick Kuijpers
  • 267
  • 3
  • 3
1

@ksht's answer is basically correct. For those looking for the simple,brief answer it is this:

Because the client app, (browser or native app), can have the delivered token intercepted. The oauth implicit flow does allow this but only under very specific circumstances. In all other cases either the browser can leak info (hacks in the OS, browser bugs , plugins) or for native apps your custom url scheme that maps the redirect url to the app can be intercepted. So the workaround is send back a code instead of a token (over tls) and use PKCE to ensure that the code can be securely exchanged for a token.

Frank
  • 903
  • 7
  • 14