expirers_in and multiple scope types - oauth-2.0

OAuth 2.0 v30 defines expires_in to specify Client time before token will expire. This works well when you have single duration for all scopes asked in request by Client. When there're more then one type of scopes: like offline - online, for example (or short living / long living if you wish) what expiration duration should the OAuth provider return?

The user gives a client the permission to access resources within certain scopes on his behalf. This permission is basically granted for an unlimited time for all scopes (as he has no influence on how it is handled by the provider), at least until the user manually revokes the permission on provider side. If he only revokes part of the scopes, the currently issued access_token is made invalid and the client has to ask for a new one (which then only has limited scope) using the refresh_token.
The reason for expiring tokens is that when they are stolen, an attacker only has access for a limited time. So the expires_in time you set as a provider should depend on how much you trust the client, if he can keep the tokens secret and not the scopes.

Related

What is the point of using refresh token instead of username password pairs?

I understand the benefit that if we use a refresh token, the requests containing credentials or refresh tokens are reduced hugely because a client to do some meaningful job in our services can send numerous requests during a period stipulated by an access token. For example, I can send 100 requests in 5 minutes once I attain an access token. Those 100 requests do not contain my credentials, so the security has increased.
My question is what are the benefits of using refresh tokens instead of username and password pair?
I've read many answers and articles about this but they cannot go beyond reiterating that we don't have to expose our credentials through refresh tokens. But who cares about the credentials as long as I got the refresh token? I might as well send my username and password to get a new access token. It effectively supplants the credentials for authentication.
A refresh token still only has restricted privileges, scoped to the client application. It allows you to get new access tokens with privileges (scopes and claims) the app needs, for the lifetime of the user session.
Example properties might be as follows:
Refresh token lifetime: 4 hours
Access token lifetime: 30 minutes
Access token scopes: orders_write benefits_read
subject claim: user123
subscription_level claim: silver
When access tokens are played against APIs, the API's authorization logic restricts logic based on scopes and claims in the token. Eg the user can only access their own orders or benefits their subscription level allows.
Whereas a user's credentials might be usable across many apps, some of which have more sensitive privileges.

Refreshed Token could be revoked 50 times per account

I tried to add YouTube Video from the third party and After one day, I got the success in doing so. But While uploading a video the access token is required and in order to get that access token the user must be logged in. And the expiration time for that access token is 3600 seconds( 1 hr).
Now, There are some of my questions regarding this.
Is there anyway, by which I can refresh access token.
If some one has G Suite account, then Is there any special values for expiration time, or it remains the same?
As per the documentation, I can have maximum 50 tokens, So is there any alternative for it, So that I can get valid token after 50 requests.
To answer your question for number 1, you can check the documentation here.
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.
If you use a Google API Client Library, the client object refreshes the access token as needed as long as you configure that
object for offline access.
If you are not using a client library, you need to set the access_type HTTP query parameter to offline when redirecting the
user to Google's OAuth 2.0 server. In that case, Google's
authorization server returns a refresh token when you exchange an
authorization code for an access token. Then, if the access token
expires (or at any other time), you can use a refresh token to obtain
a new access 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.
About the G Suite account, it was stated 24 Hours in the documentation. Note:
In this SO post answer, the function of Access Token and Refresh Token was discussed.
I am not sure if there are ways to alter the limits because of security reasons.
To clearly differentiate these two tokens and avoid getting mixed up,
here are their functions given in The OAuth 2.0 Authorization
Framework:
Access Tokens are issued to third-party clients by an authorization server with the approval of the resource owner. The
client uses the access token to access the protected resources hosted
by the resource server.
Refresh Tokens are credentials used to obtain access tokens. Refresh tokens are issued to the client by the authorization server
and are used to obtain a new access token when the current access
token becomes invalid or expires, or to obtain additional access
tokens with identical or narrower scope.

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.

Using Spring oAuth2 impl, is it possible to "downgrade" the scopes of an access token during a refresh-token grant?

I have two clients, one Public Client used by regular end-users logging in via our web page or native apps and one Confidential Client for our admin system. Both issues two JWT's, one Access Token and one Refresh Token.
The Public Client is not allowed to issue admin rights. The Access Token is short lived, and the Refresh Token has infinite life span.
The Confidential Client is allowed to issue admin scopes. The Access Token is short lived, and the Refresh Token lives 24 hrs.
Is it possible, using Spring Security and their oAuth2 implementation, to downgrade the admin user once the refresh token is expired? That is, once the user have been logged in for 24hrs, the user is not totally logged out, but on the next login he gets two new JWT's, one Access Token for regular user access and one matching Refresh Token for that access level. I guess I'm looking for some kind of hook in the Spring Security framework that allows me to handle token expiration in a customised way.
There's a sentence on your question that confuses me a bit, but I wanted to elaborate on other aspects so this did not fit in a comment.
... the user is not totally logged out, but on the next login he gets two new JWT's, one Access Token for regular user access and one matching Refresh Token for that access level.
What do you exactly mean with on the next login? My confusion here is that if the objective is not to logout the user, then there won't be a next login. I guess this could mean that almost to the end of the refresh token expiration you would want to do your downgrade request and use the still valid refresh token to get a new pair of tokens with less permissions.
According to the OAuth specification you can perform a refresh token request and ask the server for an access token that has less scopes than the one you currently have. However, it also dictates that if a new refresh token is returned, then that token needs to have the exact same scope as the refresh token included in the request.
Personally, for this scenario I would consider instead of downgrading tokens just ensure that in order to perform any administrator related operation the user must be an administrator and actually provided his credentials in the last 24 hours. You could accomplish this by tracking the date and time a given user actually performed a login (by providing their credentials) and then authorize administrator actions based on that value. This way you can increase the lifetime of refresh tokens for the confidential client and only force the administrators to login again if they want to perform a privileged tasks and their current tokens aren't fresh enough.
Finally, still on the subject of refresh tokens (with focus on the security considerations section)... when you say web app for the public client I'm assuming it's a browser-based Javascript application. If this is correct it's generally not recommended to use refresh tokens for these applications because refresh tokens are usually long-lived (in your case they seem to never expire) and the browser cannot ensure secure storage for them. This increases the likelihood of them leaking which would give an attacker access to the application for the lifetime of the token. You may have other constraints that make this security consideration not applicable, but I wanted to call your attention to it nonetheless.

For a B2B Enterprise REST API, should requesting an access token in oAuth2 invalidate previously granted access tokens to that Client ID?

For a B2B REST API servicing Enterprise clients who may have multiple applications using a Client ID/Secret:
If you send a request for an oAuth2 access token for a specific Client ID and Client Secret and receive an access token then later on send another request for a token with that same Client ID/Secret, should that invalidate the previous access token?
In other words, in this case, should a Client ID/Secret be able to request and use multiple valid access tokens? Are there different cases where this should be implemented or not?
OAuth2 is generally about a user delegating access to a client, so in the case where a client has many users (as it usually will), it will most definitely be using multiple access tokens since they will apply to different users.
Consider the situation where you grant access to your Google account to another online application (the client). Google issues an access token which might allow the client to read your contacts, for example, using Google's OAuth2 APIs (with your prior approval). Obviously it can only access your contacts with this token, not other people's. Google may issue many different access tokens to the same client, but each may correspond to a different user and/or resource.
The same authorization server may issue tokens for many different resources, so even in the case where there is no interaction with a user (as in the "client credentials" grant), a client may still need to manage multiple tokens.
Whether the authorization server invalidates a token when another is requested for the same user, audience, scope etc., would be implementation dependent. A client wouldn't usually need to do this and would normally use a refresh token to obtain a new token when its existing one was about to expire. I'd say it's generally more important that a user can invalidate existing tokens they have authorized, and that tokens can be invalidated for a particular client. Of course, this also requires that the resource server has some way of checking for token revocation before granting access.
Yes, a client can have several access tokens. It's meaningful, we're actually using.
Consider that tokens may have different scopes, so a client may have a token with scope "res1" for a resource and a another token with scope "res2" for a different resource.
Another use case may be to request a refresh token with several scopes, e.g. "read write" and use it to get a "read" scoped access token to initialize a management GUI, then get a new access token for each write transaction.
You can argue whether it's good design/implementation or not but it's definitely technically possible and not forbidden by the standard.

Resources