Spring oauth2 - authorization code deleted after consumed - spring-security

maybe i'm misunderstanding the authorization code grant type, but i thought that after issuing a code spring will keep the code in oauth_code table in DB forever till it will be revoked by user , but the code is deleted right after it is consumed (first time you exchange this for token),
so what is the flow here - should my clients keep the refresh tokens for getting access token later on (or when user is offline)
the spec say the return of refresh tokens is optional as written
The authorization server authenticates the client, validates the
authorization code, and ensures that the redirection URI
received matches the URI used to redirect the client in
step (C). If valid, the authorization server responds back with
an access token and, optionally, a refresh token.
so it the authorization server decide not to give refresh token there is no way for clients to offline request access token and they need to go though the authorization code process all over again ?
thanks
Shlomi

The authorization code can only be used once, and it must have a short lifetime. If you read section 4.1.2 of the spec it says
The authorization code MUST expire
shortly after it is issued to mitigate the risk of leaks. A
maximum authorization code lifetime of 10 minutes is
RECOMMENDED.
So once a code has been used there is not real reason to retain it (other than possibly to detect further attempts to use it).
The refresh token allows the client to obtain another access token. Otherwise, as you say, it needs to re-execute the authorization code flow to get one from scratch, which requires the interaction of the resource owner (the user). Usually the system would be set up to issue a refresh token or not to that client depending on whether it actually requires offline access to the resource, or whether the resource owner (user) will always be interating with it directly.

Related

How to create additional OAuth2 Access Tokens without user interaction

I have a web service that makes use of the Authorization Code grant type to get an Access Token for user data on a Resource Server, together with a Refresh Token. Now my web service launches jobs at certain points in time that should also access this user data. However,
there may be more than one job running at a time,
the user is not necessarily around when the jobs are spawned, and
the jobs may be long-running, in particular they may live longer than the validity of the Access Token.
My question is: How can I provide each job with an Access Token so that
no user interaction is required for every single job launch, and
each job can refresh its own Access Token if necessary, without invalidating other jobs' tokens?
While https://datatracker.ietf.org/doc/html/rfc6749#section-1.5 states that a refresh token can be used to obtain "additional access tokens" (emphasis mine), the spec is not so clear on whether the previous Access Token remains valid until it's expiry date (well, if it does not I wouldn't call it "additional"). Also, according to https://datatracker.ietf.org/doc/html/rfc6749#section-6 if a server issues a new Refresh Token to prevent replay attacks, then the old Refresh Token cannot be used any more, so now maybe I have an additional Access Token, but I can't really pass the Access Token and the new Refresh Token to the job, because if the job made use of that Refresh Token would then my web service couldn't use it any more.
Are there maybe any lesser-known flows that allow for this kind of unattended Access Token creation?
Normally access tokens and refresh tokens are valid till the exipration time.
Having multiple access and refresh tokens are also allowed.
However a refresh token can be revoked under following scenarios
the authorization server has revoked the refresh token
the user has revoked their consent for authorization
the refresh token has expired
the authentication policy for the resource has changed
Since you are having the background jobs running. I suggest not to use JWT Tokens for authentication. Instead you can have your custom security standards.
Like custom API Key, UserAgent for Jobs and you can pass the user information with the requset or as custom-header as well.

Why do you need authorization grant when you can just give the token out directly?

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

Are refresh tokens necessary for online applications

Per Google's docs it would seem refresh tokens are only necessary for offline applications (applications that may run into an expired access token when the user isn't around).
Access tokens periodically expire. You can refresh an access token
without prompting the user for permission (including when the user is
not present) if you requested offline access to the scopes associated
with the token.
...
Requesting offline access is a requirement for any application that
needs to access a Google API when the user is not present. For
example, an app that performs backup services or executes actions at
predetermined times needs to be able to refresh its access token when
the user is not present. The default style of access is called online.
However, a description of refresh tokens in general and this question in particular both seem to imply that refresh tokens are needed anytime you want to request a new access token.
I think I would agree with Google's explanation and not use refresh tokens. My experience with OIDC providers has been that refresh works as follows:
User requests protected resource from client server
Client server determines access token has expired.
Client server redirects user to OP auth endpoint
OP authenticates user without interaction due to cookies stored on user's browser with OP's domain.
Client server finishes the request.
The user might see a few redirects but other than that the re-authentication went by without any interaction from them. Given this, is it necessary to bother with refresh tokens if the user will always be present at the application?
My biggest concern with using refresh tokens for online apps is that it takes away transparency from the user.
Refresh tokens facilitate long term access and should be stored safely. But they also don't provide a natural way to "sign out", and (most importantly) it becomes completely opaque how, when and from where your data is accessed, as the often used scope name offline_access suggests.
OIDC offers a front channel mechanism prompt=none that largely leads to the same effect (i.e. new tokens), and without needing intermediate redirects if the re-authentication is performed inside an iframe.
Hence in my opinion you and Google are right and the answer must be: No, don't use refresh tokens if the user is present.
No, it is not necessary to bother with refresh tokens if the user will always be present at the application. The reasoning is largely the OP describes.
But there are reasons why one may still want a refresh token:
as the OP mentions the user might see a few redirects and both the UI expert and the branding guy on your team will hate this
when an access token expires in the middle of an HTML Form POST action, the redirect may have lost the context/POST-data on return; you may want to minimize this or you'll have to take appropriate (complex) POST-data-save actions
if your access token expiry is really short, the redirects create a lot of overhead and nuisance; you may not be able to control access token expiry when dealing a Providers in a different domain and when dealing with multiple Providers it will vary across them
when refreshing the access token with a redirect your application now depends on the Provider keeping an SSO session; not all Providers may do this and if they do they may do it in different ways: the SSO session duration may vary between them and the authentication method may vary; as an example: a Provider that doesn't keep an SSO session but does use 2-factor authentication will have large impact on the user experience
Imagine a scenario where you want to use the access token to update user information in almost real-time from the user info endpoint but the access token expiry is relatively short. Either you'll have to perform a lot of redirects with the nuisance as described, or you can use a refresh token.
Refresh token is essentialy a credential reference, that your client can exchange for access token, when there is no active user session.
For example if you want to periodicaly sync issues from Github with your inhouse system.
It is often misused like some kind of session. It is essential to diffirentiate those things. And scope name offline_access is there for a reason.
So in simple cases - you just rely on OP session and get new token with authorize/token endpoints combo. You should not be prompted to provide credentials as long as session is alive and consent is given for that particular app.
If you need to do some backgound stuff - ask for refresh token also.
As for question: no.
EDIT(More in-depth explanation):
if we are talking about web there are two main cases:
Client that can securely store secrets like usual web app with server page rendering and clients, that cant store secrets, like SPA apps. From that perspective there are two main flows (omitting hybrid to not over-complicate): Authorization Code Flow and Implicit Flow respectively.
Authorization Code Flow
On first request your app checks it own session(client session) and if there is none - redirects to external OP(OpenID Connect provider) authorize url. OP authenticates user according to requirements expressed in request, gathers consent and other stuff and returns authorization code. Then client asks token endpoint with it and receives access_token/id_token pair with optional refresh token if user granted offline access consent. This is important, because user can deny it for your app. After this client can request userInfo endpoint to get all user claims that were granted during consent. Those claims represent user identity and do not contain stuff like authentication method, acr etc. Those claims present in id_token alongside with expiration for example. After that client starts it own session and have option to set its lifetime equal to id_token lifetime or use it own to provide smooth UX for example. At this point you can discard access_token and id_token at all if you don't need access to other APIs(like all scopes in access_token are specific to OP and subject). If you need access to some API you can store access_token and use it for access. It becomes invalid - redirect to OP for new one. Expiration can be more lax here, because of more secure environment on server. So even 1hr is an option. No refresh tokens used at all.
Implicit Flow
In this case your lets say Angular app redirects to OP, gets its id_token and optional access_token from authorize endpoint directly and uses it to access some APIs. On every request expiration is checked an if needed, client sends request to OP in hidden iFrame, so there won't be any visible redirects as long as OP session is alive. There are some great libs for that like openid-client.js. No refresh is allowed here at all.
It is important to differentiate client session from OP session, token lifetime and session lifetime.
To address some specific needs there is Hybrid Flow. It can be used to get authorization code and id_token for your session in one request. No chit chat over network.
So when you think about refresh token just check your needs and map them to a spec :) And if you need it anyway - store it as secure as you can.
Refresh tokens are useful for applications that keep access tokens in a server session. For example if a web application doesn't call a protected service using JavaScript XHR, but calls its backend and the backend calls the service. In this scenario, it's easier to get a new access token whenever it's needed than asking a user for a new one.
In JavaScript applications running in browsers, refresh tokens cannot be used, because you need a client secret to get an access token from the /token endpoint and you cannot keep the secret safe in such applications.
The process for getting new access tokens you described can be improved - an application may ask for a new access token just before the current one expires, so the user doesn't get redirected to the OAuth2 server, but the application calls the /auth endpoint with prompt=none parameter in an iframe.

How does a short-lived Access Token add security?

In the answer to the question Why do access tokens expire?, the first point provided states:
[Bearer-Tokens are] short-lived and requiring refresh, they limit the time an attacker can abuse a stolen token.
But when an Access-Token is used (From a native-app), the Client uses the Refresh-Token to get a new Access Token, and sends that new token back to the requestor. So if an attacker uses somebody else's access token, he'll just be sent a brand new access token every time.
So who cares about how long the token lasts? If an attacker gets it, they have taken over the session For As Long As The Refresh Token Lasts
I already know a dozen answers to my question, but I have questions to each answer. My original question was so long because I explained every scenario and how they are inconsequential or false (as far as I know). So please try to help me understand and I'll comment if I think the answer has caveats.
Addition/Edit - Hoping for more answers with my additional information
Web Page calls a Client with Resource Owner (User) Credentials
Client calls the Auth Server and gets an Access and Refresh Token. The Access Token will expire in 5 minutes, the Refresh Token will expire in hours or days or whatever.
Client sends the Access Token to the Web Page
Resource Owner (User) uses the web page
Web Page sends the Access Token to the Client
Client sends the Access Token to the Resource Server
Resource Server checks the Access Token in any number of ways
Resource Server sends Resources to the Client
Client sends Resources to the Resource Owner
Resource Owner (user) Continues to use the Web Page
The Client, either during Each Request or every 4 minutes and 30 seconds, uses the Refresh Token to get a new Access Token
The Client, either during Each Request or every 4 minutes and 30 seconds, sends a New Access Token to the Active Resource Owner
Yes? No? Since the Resource Owner is Actively using the web site, the web site is in constant communication with the Client, and the Client gets a new Access Token (Using the Refresh Token) and sends it back to the web site, so the Active user can continue using the site without being kicked out every 5 minutes.
Therefore, if ANY Person gets ahold of that Access Token, and are hitting the Client with it, the Client will continue to send new Access Tokens to whoever has that Access Token. Granted: After a single refresh, one of those two people will have a bad Access Token and be booted, but not necessarily the right person.
Your point seems to be that if an attacker can take over your browser session then they will be able to access the third-party resource for the entire length of the refresh token, as you've described. So what's the point of having a short-lived access token?
There's certainly some truth to that, but there are two general responses:
Using a refresh token makes it practicable to invalidate the user if the third-party figures out that the session has been taken over by an attacker.
The access token / refresh token system is used to prevent or limit other kinds of attacks that you haven't mentioned.
Regarding the first point, remember that the access token is sent to the resource server, not the authorization server. Although there's nothing in the specification that prevents the resource server from checking the validity of the user, in practice that could present performance issues. Access tokens are typically designed to be self-validating, without requiring access to some external resource.
Given that, the only way to invalidate a user is to do it on the authorization server when the refresh token is sent in. The authorization server sees that this user has been marked as compromised, and refuses to send a new access token.
Regarding the second point, there are plenty of other security scenarios that OAuth is designed to protect against other than a user's browser session being taken over by an attacker. What if someone is able to get ahold of the access token in some other way? Since the access token itself isn't generally used to get access to the client (see below), they won't be able to get the client to refresh the token for them, and therefore the fact that the access token is short-lived will be a security advantage.
As a reference, both of these points are made succinctly in this email to the Oauth Working Group mailing list.
Looking specifically at the flow you described in your post, I think your confusion is rooted in the idea that the client (web server) sends the user agent (the browser) the access token (your step 3), and that that token (in the form of a cookie) is what the client uses to authenticate the user agent. Although it's possible for a web framework to do those things, neither one is a part of OAuth (nor generally true of web frameworks, in my experience).
Access tokens are short-lived, refresh tokens are long-lived. Access tokens are presented to the Resource Server (and only the Resource Server) that hosts the protected content to get access. Refresh tokens are presented only to the Authorization Server, never to the Resource Server. So when an attacker obtains an access token, he can use it for the lifetime of the access token to get access to the protected content.
When the access token expires there's no way to get a new one unless he has obtained the refresh token as well. Besides that, when using the refresh token the client typically authenticates itself to the Authorization Server, so even when the attacker got the refresh token, he would also need the Client's credentials to use it to get a new access token.

Is function of authorization code and refresh token duplicated in design of 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.

Resources