OhadR
OhadR

Reputation: 8879

oAuth2.0: Why need "authorization-code" and only then the token?

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?

Upvotes: 56

Views: 9404

Answers (7)

jeti
jeti

Reputation: 1908

A high level overview which helped me understand the role of authorization code:

  1. As a first step you need to register your app with the OAuth provider. You need to define a redirect_url which is a URL the browser will be redirected to with the authorization code in the URL. During the registration process you get a client_id and a client_secret - these are like the username + password of your app to the OAuth provider.

  2. The user clicks on your login button.

  3. The user is redirected to the 3rd party OAuth provider login page. You have to send your client_id in order to open that page.

  4. After the successful login the browser is redirected to the URL you specified at the registration. The authorization code is received in the URL. This is important: the user initiates the login process form the browser so when the OAuth provider makes a redirection it redirects your browser!

  5. The authorization code is in the browser URL so it is not really safe because it can be stolen. This is why the temporary authorization code is received at this step and not the access token.

  6. So now your browser makes a request to your backend with the authorization code .

  7. Your backend can now ask for an access token from the OAuth provider using the authorization code + the client_id + client_secret.

  8. Your client_secret lives only on your server so even if the attacker stole the authorization code the attacker would not be able to create an access token because the attacker would need to have access to your client_secret too!

Upvotes: 0

Frank
Frank

Reputation: 1080

@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.

Upvotes: 1

davidhq
davidhq

Reputation: 4760

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.

Upvotes: 26

Nick Kuijpers
Nick Kuijpers

Reputation: 277

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.

Upvotes: 2

Jan Gerlinger
Jan Gerlinger

Reputation: 7415

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.

Upvotes: 10

ksht
ksht

Reputation: 169

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.

Upvotes: 10

Fizer Khan
Fizer Khan

Reputation: 92935

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.

Upvotes: 2

Related Questions