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?
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.
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.
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.
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.
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.
#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.
Related
Imagine you're going through a standard OAuth2 process to retrieve an access_token for some third-party API. This is the usual process.
User is redirected to http://some-service.com/login
User successfully logs in and is redirected to some destination http://some-destination.com. In this step, there's usually a code parameter that comes with the request. So the actual URL looks like http://some-destination.com?code=CODE123
I need to use CODE123 to request an access_token that can be used to authorize my future API calls. To do this, there's an endpoint that usually looks like this (I am using Nylas as an example but should be generic enough):
As you can see, it requires me to POST the code from above (CODE123) along with client_id and client_secret like this: http://some-service.com/oauth/token?code=CODE123&client_secret=SECRET&client_id=ID. As a response, I get an access_token that looks like TOKEN123 and I can use this to make API calls.
QUESTION
Until step 2, everything happens in the client side. But in step 3, I need to have client_id and client_secret. I don't think it's a good idea to store these values in the client side. Does that mean I need to have a backend server that has these two values, and my backend should convert CODE123 to TOKEN123 and hand it to the client side?
As you probably know, the question describes the most common (and usually, the more secure) OAuth "Authorization Code" flow. To be clear, here's an approximation of the steps in this flow:
User indicates that they wish to authorize resources for our application (for example, by clicking on a button)
The application redirects the user to the third-party login page, where the user logs in and selects which resources to grant access to
The third-party service redirects the user back to our application with an authorization code
Our application uses this code, along with its client ID and secret to obtain an access token that enables the application to make requests on behalf of the user only for the resources that the user allowed
Until step 2, everything happens in the client side. But in step 3, I need to have client_id and client_secret. I don't think it's a good idea to store these values in the client side. Does that mean I need to have a backend server that has these two values[?]
You're correct, it's certainly not a good idea to store these values in the client-side application. These values—especially the client secret—must be placed on a server to protect the application's data. The user—and therefor, the client application—should never have access to these values.
The server uses its client ID and secret, along with the authorization code, to request an access token that it uses for API calls. The server may store the token it receives, along with an optional refresh token that it can use in the future to obtain a new access token without needing the user to explicitly authorize access again.
...and my backend should convert CODE123 to TOKEN123 and hand it to the client side?
At the very least, our server should handle the authorization flow to request an access token, and then pass only that token back to the client (over a secure connection).
However, at this point, the client-side application (and the user of that client) is responsible for the security of the access token. Depending on the security requirements of our application, we may want to add a layer to protect this access token from the client as well.
After the server-side application fetches the access token from the third-party service, if we pass the access token back to the client, malware running on the client machine, or an unauthorized person, could potentially obtain the access token from the client, which an attacker could then use to retrieve or manipulate the user's third-party resources through privileges granted to our application. For many OAuth services, an access token is not associated with a client. This means that anyone with a valid token can use the token to interact with the service, and illustrates why our application should only request the minimum scope of access needed when asking for authorization from the user.
To make API calls on behalf of a user more securely, the client-side application could send requests to our server, which, in turn, uses the access token that it obtained to interact with the third-party API. With this setup, the client does not need to know the value of the access token.
To improve performance, we likely want to cache the access token on the server for subsequent API calls for the duration of its lifetime. We may also want to encrypt the tokens if we store them in the application's database—just like we would passwords—so the tokens cannot be easily used in the event of a data breach.
Watching this video, it details in OAuth2 that the client application first has to get the authorization grant from the Authorization server and then use that grant to get a token before being able to access the resource server. What purpose does the grant serve? Why not give the client the token right away after the user signs on with his/her username and password?
Because it is more secure, for some application types.
What you describe is so called authorization-code-flow. It is normally used for "classical" web applications, where only the backend needs to access resource server. The exchange of authorization code to access token happens on the backend and access token never leaves it. Exchange can be done only once and in addition client id and secret (stored on the backend) are necessary.
Single-Page-Applications often use implicit-flow where access token is delivered to the frontend directly in the URL.
See more here:
IdentityServer Flows
EDIT: Q: "I still don't see how it is more secure given that you have to have the grant in order to get the token. Why need 2 things instead of just 1 thing to access the resource? If someone steals the token, they can access the resource anyway – stackjlei"
"Stealing" access token will work independent on how your application acquires it. However, stealing access token on the backend is much more difficult than on the frontend.
Authorization code is delivered to the backend also over the frontend but the risk that someone intercepts and uses it is tiny:
It can be exchanged only once.
You need client-id and client-secret in order to exchange it. Client-secret is only available on the backend.
Normally, authorization code will be exchanged by your backend to access-token immediately. So the lifetime of it is just several seconds. It does not matter if someone gets hold of used authorization code afterwards.
In your scenario there could be two servers, an Authorization and a Resource one.
It could be only one as well, but let's imagine this scenario.
The purpose of the Authorization Server is to issue short lived access tokens to known clients. The clients identify themselves via their CLientID and CLientSecret.
The Authorization Server ( AS ) holds the list of clients and their secrets and first checks to make sure the passed values match its list. If they do, it issues a short lived token.
Then the client can talk to the Resource Server ( RS ), while the token is valid. Once the token expires, a new one can be requested or the expired one can be refreshed if that is allowed by the Authorization Server.
The whole point here is security, Normally, the access tokens are passed in the Authorization header of the request and that request needs to be over https to make sure that the data can't be stolen. If, somehow, someone gets hold of an access token, they can only use it until it expires, hence why the short life of the tokens is actually very important. That's why you don't issue one token which never expires.
You have different type of OAuth. On type doesn't require to use the 'grant' authorization. It depend who are the user/application, the ressource owner and the server API.
This way, you - as a user - don't send the password to the application. The application will only use the grant token to gain access to your ressources.
I think this tuto is a pretty good thing if you want more details
https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2
I'm building a web app that uses the Oauth2.0 protocol. I have registered my app with the authorization server and received my client id and client secret.
I'm now working on Authorization part and specifically using the Authorization Code grant type. In that process i'm sending the user to the authorize endpoint with the following query parameters:code, client_id, redirect_uri, scope and state. (omitting the client_secret)
The problem that i'm dealing with is i'm getting an error back saying I need to provide the client_secret as well.
I was under the impression the client_secret is not needed at this part and shouldn't be sent in this request but rather when the client sends the authorization code (along with id & secret) to obtain the access token.
So my question is, Is it wrong (against oauth 2 protocol) that the authorization server requires the client secret to be sent in the request for the authorization code?
I am not 100% sure of this, but I did some research myself and what I found is that is not a real problem not to keep the "client secret" a secret. The only possibility of someone malicious being able to get through the Authorization specs is prevented by some facts:
1. Client need to get authorization code directly from the user, not from the service
Even if user indicates the service that he/she trusts the client, the
client cannot get authorization code from the service just by showing
client id and client secret. Instead, the client has to get the
authorization code directly from the user. (This is usually done by
URL redirection, which I will talk about later.) So, for the malicious
client, it is not enough to know client id/secret trusted by the user.
It has to somehow involve or spoof user to give it the authorization
code, which should be harder than just knowing client id/secret.
2. Redirect URL is registered with client id/secret
Let’s assume that the malicious client somehow managed to involve the
user and make her/him click "Authorize this app" button on the service
page. This will trigger the URL redirect response from the service to
user’s browser with the authorization code with it. Then the
authorization code will be sent from user’s browser to the redirect
URL, and the client is supposed to be listening at the redirect URL to
receive the authorization code. (The redirect URL can be localhost
too, and I figured that this is a typical way that a “public client”
receives authorization code.) Since this redirect URL is registered at
the service with the client id/secret, the malicious client does not
have a way to control where the authorization code is given to. This
means the malicious client with your client id/secret has another
obstacle to obtain the user’s authorization code.
// copy paste of hideaki answer
Concluding
OAuth2 specify that you need to inform your secret into a request if your application is a server-side based app (different than a single-page application or mobile) which does not make its source code available. However, if you can't control your base code, like in an native mobile application, you should look for another solution.
References
OAuth2 Documentation
Bear similar stack question
Simplifying OAuth2
there's two ways to fetch access token.
use authorization code to exchange it
use refresh token to refresh it
think about it!!
though the word of exchange and refresh is different,what they do are the same.
both action need to parse client id & client secret(Or signature) and token
we can just save the authorization code in our system,and again use auth code to
refresh access token just like refresh token do.
Except that authorization code is expired too soon.
so I wonder
why the designers of oauth2 designed these two concepts while not used just one single concept or say just design the authorization code and give it a long expired-time.
I am afraid that you have not understood the concepts of oauth2 too well. There aren't just two ways of getting the access token, there are more. Each is basically called a 'grant type'. I'm describing the use cases of the ones which I have deployed below :
1- Authorization code :
This is similar to the flow of "Login with Facebook" etc buttons which you see on different websites, which allow you to register/login using your facebook etc accounts. Here, on clicking this button, control is directed to Facebook, where the user enters his login credentials. If successful, an authorization code is sent to whatever redirecturl you entered while registering as a developer with Facebook. You then use this authorization code to request the access token service to get the access token which you then use whenever accessing any Facebook webservices to get the user's details.
2- Client credentials :
If you are running your own webservices and you want to allow access only to valid clients, then this is the grant type you would use. For example, you are running your webservices and now you want to consume it in your own native mobile app which you distribute through any app store. This will ensure that only those who installed your app will be able to access your webservice.
3- User credentials :
Same as above, only in this case this would allow you to authenticate a registered user as well and then give access to user restricted services like my account etc.
4- Refresh token :
By design, the access token service gives an access token as well as a refresh token. You would use the refresh token obtained from it here to refresh an expired access token. Essentially, this does not generate a new access token, it only "refreshes" an existing token. It will give you a new access token and refresh token and extend the expiry time. When this access token expires, you again call refresh token using the refresh token obtained last time, and keep repeating the process every time the token expires.
According to RFC 6749 10.5 The authorization codes are short lived and single-use. Therefore, you cannot use them again and again to get new authorization tokens.
Authorization codes MUST be short lived and single-use. If the
authorization server observes multiple attempts to exchange an
authorization code for an access token, the authorization server
SHOULD attempt to revoke all access tokens already granted based on
the compromised authorization code.
There are some additional misconceptions that seem to be presented here, so I wanted to help clear them up.
The differences between an access token and a refresh token can be summarised as follows:
An access token is used to provide access to restricted resources to an authorized client after authentication has taken place.
A refresh token, on the other hand, is used by a client in order to retrieve new access tokens with identical or narrower scopes.
The different between the Authorization Code Grant and the Implicit Grant (as well as their usages) help to illustrate how both should be used.
In general, the Authorization Code Grant should be preferred over the Implicit Grant unless a resource is being accessed directly via a publicly implemented client (e.g., browser-run code) or there is a specific reason that the Authorization Code Grant cannot be used (e.g., feasibility or performance). This is explained in the RFC definition for the Implicit flow.
During an Implicit Grant, access tokens are exposed to the user-agent which could lead to them being compromised since they are no longer under the control of a server app (confidential client) that could otherwise be requesting the protected resources. This is why refresh tokens are not issued during Implicit Grants. Though access tokens might be exposed, they are short-lived. Resource tokens, on the other hand, are long-lived and can be used to retrieve new access tokens.
The Authorization Code Grant, on the other hand, prevents the potential for refresh tokens to be exposed. During this grant, the authorisation server issues a code instead of tokens. The code is then passed by the user-agent to the client application which exchanges the code with the authorization server to retrieve access and refresh tokens. Since the code exchange is performed directly between the client application and a trusted authorization server, a refresh token can be securely issued.
The RFC spec cautions that the security implications of implementing the Authorization Code Grant in a public client versus a confidential (e.g., server-side) client should be seriously considered. "More OAuth 2.0 Surprises: The Refresh Token" clears up a few misconceptions and furthers the idea that auth codes should not be sent directly by the user-agent to the auth server in order to retrieve refresh tokens, though the OAuth 2.0 spec does not technically dictate this.
Answer from #ComfortableDust has the answer to original question. Just quoting the exact text from his reply
The Authorization Code Grant, on the other hand, prevents the potential for refresh tokens to be exposed. During this grant, the authorisation server issues a code instead of tokens. The code is then passed by the user-agent to the client application which exchanges the code with the authorization server to retrieve access and refresh tokens. Since the code exchange is performed directly between the client application and a trusted authorization server, a refresh token can be securely issued.
OAuth 2.0 has multiple workflows. I have a few questions regarding the two.
Authorization code flow - User logs in from client app, authorization server returns an authorization code to the app. The app then exchanges the authorization code for access token.
Implicit grant flow - User logs in from client app, authorization server issues an access token to the client app directly.
What is the difference between the two approaches in terms of security? Which one is more secure and why?
I don't see a reason why an extra step (exchange authorization code for token) is added in one work flow when the server can directly issue an Access token.
Different websites say that Authorization code flow is used when client app can keep the credentials secure. Why?
The access_token is what you need to call a protected resource (an API). In the Authorization Code flow there are 2 steps to get it:
User must authenticate and returns a code to the API consumer (called the "Client").
The "client" of the API (usually your web server) exchanges the code obtained in #1 for an access_token, authenticating itself with a client_id and client_secret
It then can call the API with the access_token.
So, there's a double check: the user that owns the resources surfaced through an API and the client using the API (e.g. a web app). Both are validated for access to be granted. Notice the "authorization" nature of OAuth here: user grants access to his resource (through the code returned after authentication) to an app, the app get's an access_token, and calls on the user's behalf.
In the implicit flow, step 2 is omitted. So after user authentication, an access_token is returned directly, that you can use to access the resource. The API doesn't know who is calling that API. Anyone with the access_token can, whereas in the previous example only the web app would (it's internals not normally accessible to anyone).
The implicit flow is usually used in scenarios where storing client id and client secret is not recommended (a device for example, although many do it anyway). That's what the the disclaimer means. People have access to the client code and therefore could get the credentials and pretend to become resource clients. In the implicit flow all data is volatile and there's nothing stored in the app.
I'll add something here which I don't think is made clear in the above answers:
The Authorization-Code-Flow allows for the final access-token to never reach and never be stored on the machine with the browser/app. The temporary authorization-code is given to the machine with the browser/app, which is then sent to a server. The server can then exchange it with a full access token and have access to APIs etc. The user with the browser gets access to the API only through the server with the token.
Implicit flow can only involve two parties, and the final access token is stored on the client with the browser/app. If this browser/app is compromised so is their auth-token which could be dangerous.
tl;dr don't use implicit flow if you don't trust the users machine to hold tokens but you do trust your own servers.
The difference between both is that:
In Implicit flow,the token is returned directly via redirect URL with "#" sign and this used mostly in javascript clients or mobile applications that do not have server side at its own, and the client does not need to provide its secret in some implementations.
In Authorization code flow, code is returned with "?" to be readable by server side then server side is have to provide client secret this time to token url to get token as json object from authorization server. It is used in case you have application server that can handle this and store user token with his/her profile on his own system, and mostly used for common mobile applications.
so it is depends on the nature of your client application, which one more secure "Authorization code" as it is request the secret on client and the token can be sent between authorization server and client application on very secured connection, and the authorization provider can restrict some clients to use only "Authorization code" and disallow Implicit
Which one is more secure and why?
Both of them are secure, it depends in the environment you are using it.
I don't see a reason why an extra step (exchange authorization code
for token) is added in one work flow when the server can directly
issue an Access token.
It is simple. Your client is not secure. Let's see it in details.
Consider you are developing an application against Instagram API, so you register your APP with Instagram and define which API's you need. Instagram will provide you with client_id and client_secrect
On you web site you set up a link which says. "Come and Use My Application". Clicking on this your web application should make two calls to Instagram API.
First send a request to Instagram Authentication Server with below parameters.
1. `response_type` with the value `code`
2. `client_id` you have get from `Instagram`
3. `redirect_uri` this is a url on your server which do the second call
4. `scope` a space delimited list of scopes
5. `state` with a CSRF token.
You don't send client_secret, You could not trust the client (The user and or his browser which try to use you application). The client can see the url or java script and find your client_secrect easily. This is why you need another step.
You receive a code and state. The code here is temporary and is not saved any where.
Then you make a second call to Instagram API (from your server)
1. `grant_type` with the value of `authorization_code`
2. `client_id` with the client identifier
3. `client_secret` with the client secret
4. `redirect_uri` with the same redirect URI the user was redirect back to
5. `code` which we have already received.
As the call is made from our server we can safely use client_secret ( which shows who we are), with code which shows the user have granted out client_id to use the resource.
In response we will have access_token
The implicit grant is similar to the authorization code grant with two distinct differences.
It is intended to be used for user-agent-based clients (e.g. single page web apps) that can’t keep a client secret because all of the application code and storage is easily accessible.
Secondly instead of the authorization server returning an authorization code which is exchanged for an access token, the authorization server returns an access token.
Please find details here
http://oauth2.thephpleague.com/authorization-server/which-grant/
Let me summarize the points that I learned from above answers and add some of my own understandings.
Authorization Code Flow!!!
If you have a web application server that act as OAuth client
If you want to have long lived access
If you want to have offline access to data
when you are accountable for api calls that your app makes
If you do not want to leak your OAuth token
If you don't want you application to run through authorization flow every time it needs access to data. NOTE: The Implicit Grant flow does not entertain refresh token so if authorization server expires access tokens regularly, your application will need to run through the authorization flow whenever it needs access.
Implicit Grant Flow!!!
When you don't have Web Application Server to act as OAuth Client
If you don't need long lived access i.e only temporary access to data is required.
If you trust the browser where your app runs and there is limited concern that the access token will leak to untrusted users.
Implicit grant should not be used anymore, see the IETF current best practices for details. https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-18#section-2.1.2
As an alternative use a flow with response type code; for clients without possibility to securely store client credentials the authorization code with PKCE flow should be your choice.
From practical perspective (What I understood), The main reason for having Authz code flow is :
Support for refresh tokens (long term access by apps on behalf of User), not supported in implicit: refer:https://www.rfc-editor.org/rfc/rfc6749#section-4.2
Support for consent page which is a place where Resource Owner can control what access to provide (Kind of permissions/authorization page that you see in google). Same is not there in implicit . See section : https://www.rfc-editor.org/rfc/rfc6749#section-4.1 , point (B)
"The authorization server authenticates the resource owner (via the user-agent) and establishes whether the resource owner grants or denies the client's access request"
Apart from that, Using refresh tokens, Apps can get long term access to user data.
There seem to be two key points, not discussed so far, which explain why the detour in the Authorization Code Grant Type adds security.
Short story: The Authorization Code Grant Type keeps sensitive information from the browser history, and the transmission of the token depends only on the HTTPS protection of the authorization server.
Longer version:
In the following, I'll stick with the OAuth 2 terminology defined in the RFC (it's a quick read): resource server, client, authorization server, resource owner.
Imagine you want some third-party app (= client) to access certain data of your Google account (= resource server). Let's just assume Google uses OAuth 2. You are the resource owner for the Google account, but right now you operate the third-party app.
First, the client opens a browser to send you to the secure URL of the Google authorization server. Then you approve the request for access, and the authorization server sends you back to the client's previously-given redirect URL, with the authorization code in the query string. Now for the two key points:
The URL of this redirect ends up in the browser history. So we don't want a long lived, directly usable access token here. The short lived authorization code is less dangerous in the history. Note that the Implicit Grant type does put the token in the history.
The security of this redirect depends on the HTTPS certificate of the client, not on Google's certificate. So we get the client's transmission security as an extra attack vector (For this to be unavoidable, the client needs to be non-JavaScript. Since otherwise we could transmit the authorization code via fragment URL, where the code would not go through the network. This may be the reason why Implicit Grant Type, which does use a fragment URL, used to be recommended for JavaScript clients, even though that's no longer so.)
With the Authorization Code Grant Type, the token is finally obtained by a call from the client to the authorization server, where transmission security only depends on the authorization server, not on the client.