I am trying to understand the token abuse scenarios in OpenID/OAuth 2.0 context.
In the grant_type=authorization_code scenario, the access token and the refresh token are available to a client app after successful user authorization. Token refresh makes it easy for client app to keep using the user resource for a practically infinite amount of time.
Is it possible to limit the use of the access and refresh tokens by client app?
Scenario: a user would like to authorize client app access to the resource for only until he closes the browser. The tokens should be invalidated after that.
For such control, user completely depends on how the Identity Provider is implemented. It would be possible to implement Identity Provider in such a way, e.g. it could ask user when the authentication session should expire on the consent screen. However, I've never seen such an implementation. Some Identity Providers allow to revoke issued tokens manually, but this is often hidden behind deep navigation on the Identity Provider's site.
Related
As said in OAuth2 rfc6749
The implicit grant type is used to obtain access tokens (it does not
support the issuance of refresh tokens) and is optimized for public
clients known to operate a particular redirection URI. These clients
are typically implemented in a browser using a scripting language
Refresh tokens are not suitable for implicit grant.
My question is:
How a mobile app, will refresh the access_token once it expires?
How the big ones in the market are doing this? Which practices they follow?
I know it is not following security recomendations, but it´s a good practice to make an long-lived access_token in this case? It can get annoying to need to re-authenticate each 30 min you use an app, or you close and reopen it.
As necessary permissions don´t change, a silent log-in on every app start, will be a choice to consider?
You don't necessarily need a refresh token to allow continued usage once an access token expires. If you must insist your clients use the implicit flow, then they may be able to make use of cookies and redirects to keep getting short-lived tokens without user interaction. Providing your client apps are using an HTTP agent which can use permanent cookies. e.g. apps that run in a web browser.
The key then is keeping the user signed into the identity provider the first time the token is requested.
This is done for example by the Identity provider (you I guess?) creating an HTTP cookie for the user agent to persist. Most big identity providers will do this - i.e. keep you signed in.
Now, when the token expires your client app will send the user back through the Oauth process again but, because the user has remained logged in to the identity provider, the identity provider can authenticate the user from the cookie without prompting for credentials.
If your clients instigate this token renewal on a background thread they can request the token as normal and, through the magic of HTTP redirects and cookies, get back a new token from you with no user action required.
Again - this alternative to refresh tokens relies on the client device being able to utilise permanent cookies, and your users remaining signed in and your auth server handling http cookies. If your clients are using native apps this solution may not work.
As in the future you will have 100s of clients maybe your auth plaform should offer different auth flows to different clients.
This article on mobile apps and implicit flow may be of interest to you.
Native apps are supposed to use the Auth code grant. So you can use refresh tokens. There is an RFC that discusses reasons (mainly security) for that as well as platform specific details. There is an important implication - the /token endpoint of your OAuth2 provider should not require authentication for getting tokens, because your application cannot keep its client secret safe.
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.
I need to implement Authorization/Authentication for an Angular2 Client Side WebApp to talk to a Resource Server(WebApi).
I am investigating IdentiyServer4 and choosing a Grant Type / Flow. HERE
Resource Owner Password Credentials Grant(What we use now.) "This is so called “non-interactive” authentication and is generally not recommended".
Authorization Code & Hybrid <- Solution to Implicit Flow not allowing Refresh Tokens.(Seems fairly complex to me. But is this the way to go?)
Implicit Flow - Recommended for SPA's everywhere I look. But does not support Refresh Tokens..
With Implicit Flow, how do I not require the user of the SPA to have to type in a password every say 3600 sec? A recommended access_token lifetime. I presume there is something I do not understand about getting the new authorization URL.
Resources I have looked at.
IdentityServer4 Grant Types
Implicit Grant Flow for Client-Side Apps
A Guide To OAuth 2.0 Grants
SO - Oauth2 Implicit Flow with single-page-app refreshing access tokens
Thanks for the answer Scott. I have some reading to do.
Getting Started with IdentityServer4
When using the Implicit flow you can still use your own cookie lifetimes (ie longer than 3600 seconds). To get around access tokens expiring, you can use the fact that the user is still authenticated within IdentityServer to fetch another access token, without the need for refresh tokens.
The IdentityModel OpenID Connect JS Client does this by firing an event just before access token expiration and using an iframe to make a fresh authentication request to IdentityServer. If the user is still logged into IdentityServer (which has a different, typically longer lived cookie than your own client application), then IdentityServer sends back fresh tokens just like a normal authentication request. This happens in the background with no interaction from the user and no interruption.
Check out the automaticSilentRenew functionality in this library for implementation specifics.
By the way, the Implicit, Authorization Code and Hybrid grant types, in the case of IdentityServer, are OpenID Connect grant types. Resources referring to the OAuth versions may not apply to your use case.
I'm fairly new to Oauth and I am wondering if a specific flow is supported by any of the Oauth flows. I want to be able to identify a user and allow that user to perform unsecure actions even after their token has expired. The user would only be forced to reauthenticate if they request to perform a secure operation. I currently do not see any flow that will support this.
I have thought of the following solution using refresh tokens but not sure I am possibly violating any oauth patterns or if there is a better way.
1) Issue access token for X amount of time. Lets say 2 hours.
2) Upon token expiration, refresh token is used to get a new access token. The new token will contain a claim that identifies that the user only has unsecure access.
3) If secure resource is requested, request will be denied with a 401 response code indicating that the token is invalid.
4) Application will have to ask for user credentials in order to receive a new access token.
Any thoughts on this?
This is really up to the interaction between the Resource Server and the Client and certainly with the boundaries of standard OAuth 2.0 . The only thing that OAuth 2.0 standardizes in that interaction is the way in which the access token is presented. All other behavior is left up to the application implementor.
The Resource Server would allow access to unsecure resources/operations regardless of the validity of the access token, or even if there's no access token presented at all. Only upon accessing a secured resource the flow would would as you describe.
I don't see value in producing access tokens that identifies "unsecure access". That token would have the same semantics as an expired token or no token at all, so there's no need for an access token to cover that case.
I am trying to implement Oauth 2.0 provider. I am confused on access token grants. I am using oauth2orize module in node.js.
I am confused on Should I remove all access token related to specific user when user logouts from auth server? I am building mobile and single page app for browser and I am using Resource owner password credential flow. How long should access token be valid for and should it expire on logout?
Generally, an app will revoke an access token just prior to performing logout. Typically, the app will revoke a refresh token if it got one, as that will also invalidate any and all access tokens.
From the perspective of the authorization server, I would keep these things separate and implement both:
Revoke (RFC 7009)
Logout (OpenID Connect)
Then, the clients can use either / both of these as they need. If you have some constraints in your environment, you may be able to automatically revoke tokens during logout in your authorization server. Generally though, an it should allow for both to be used independently and put the client in control.