Reputation: 8879
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
Reputation: 1908
A high level overview which helped me understand the role of authorization code
:
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.
The user clicks on your login button.
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.
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!
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
.
So now your browser makes a request to your backend with the authorization code
.
Your backend can now ask for an access token
from the OAuth provider using the authorization code
+ the client_id
+ client_secret
.
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
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
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
Reputation: 277
I think it is like this;
When we use the authorization code, we have 2 verification parts;
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)
Upvotes: 2
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
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
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