Implementing a since-last-activity timeout with OAuth - oauth

We are:
Using OAuth for both authorization and authentication
Using the implicit-grant flow (i.e. client-side flow)
Issuing relatively short-lived access tokens (measured in hours, not weeks)
I want to offer a comparable experience to the traditional expiring-cookie policy, where you get a certain amount of time that your credentials will work, but if you stay active on the site that window continually resets. I'm realizing that this is not straightforward in OAuth. Yes, tokens are issued with an expiry time, but most implementations keep that time fixed regardless of activity.
This isn't so weird when issuing extremely long-lived tokens as one does when authorizing an integration (like, say, a Twitter app). But it's weird when using OAuth for user-facing authentication. If we issue a short-lived token and the user goes for a big session on our site, their access may run out abruptly even though they are in the middle of something. Even if we issued a token valid for 24 hours, if the user comes back 23.75 hours later, they're going to get 15 good minutes and then suddenly get kicked off.
I'm trying to figure out how to offer my users a better experience while sticking to OAuth mechanics. So far, my best idea is to change the server-side implementation to update the expiry date on the token on each authenticated request (this only works because our tokens have a server-side component - I don't know how it could work if we went the self-contained token route). And then, to keep the client appraised of the updated expiry time, we'll want to send that back with our response, maybe in a header, or a meta attribute in the JSON object.
This approach seems a little complicated, but workable. Is there a better way? Has anyone else dealt with this issue? Am I nuts for even trying?

Related

What's the purpose of setting expiry of client token if I can just refresh tokens everytime?

I'm using the Dailymotion API which uses Oauth2, their client tokens expire in 36000 seconds (10 hours), so I thought of creating new tokens for every call with the refresh token URL provided. Also, I didn't find any warnings in the documentation preventing me from doing this, is this a bad practice?
creating a new token on every requests is not the best way to proceed.
During your request, you can check (ex: with a "try") if your access token has expired then request new one with your given refresh token only if necessary.
If you are using a language like PHP, Python, Javascript, ... you can save much time using the available SDKs that already implement these mechanisms.
cf. https://developer.dailymotion.com/tools/sdks/
Yes, it is a bad practice, even though it's feasible. Authorization Servers might impose rate limiting on your client so that at some point you won't be able to refresh the token.
The access token must have expiration time for security reasons. If anyone manages to get hold of that token they will be able to use it only for the specified time. Good practice is to have as short expiration times as possible - e.g. 5 or 15 minutes. The 10 hours used by Dailymotion is a bit much, in my opinion, but it's their decision.
Refresh tokens should be kept securely by your client and you usually need a client secret to make a refresh request. This means that generally it's much harder for an attacker to get hold of a refresh token (or use it once they manage to steal it).

Should an oAuth server give the same accessToken to a same client request?

I am developing an oAuth2 server and I've stumbled upon this question.
Lets suppose a scenario where my tokens are set to expire within one hour. On this timeframe, some client goes through the implicit auth fifty times using the same client_id and same redirect_uri. Basically same everything.
Should I give it the same accessToken generated on the first request on the subsequent ones until it expires or should I issue a new accessToken on every request?
The benefits of sending the same token is that I won't leave stale and unused tokens of a client on the server, minimizing the window for an attacker trying to guess a valid token.
I know that I should rate-limit things and I am doing it, but in the case of a large botnet attack from thousands of different machines, some limits won't take effect immediately.
However, I am not sure about the downsides of this solution and that's why I came here. Is it a valid solution?
I would rather say - no.
Reasons:
You should NEVER store access tokens in plain text on the Authorization Server side. Access tokens are credentials and should be stored hashed. Salting might not be necessary since they are generated strings anyway. See OAuth RFC point 10.3.
Depending how you handle subsequent requests - an attacker who knows that a certain resource owner is using your service and repeat requests for the used client id. That way an attacker will be able to impersonate the resource owner. If you really return the same token then at least ensure that you authenticate the resource owner every time.
What about the "state" parameter? Will you consider requests to be the "same" if the state parameter is different? If no then a botnet attack will simply use a different state every time and force you to issue new tokens.
As an addition - generally defending against a botnet attack via application logic is very hard. The server exposing your AS to the internet should take care for that. On application layer you should take care that it does not go down from small-bandwidth attacks.
You can return the same access_token if it is still valid, there's no issue with that. The only downside may be in the fact that you use the Implicit flow and thus repeatedly send the - same, valid - access token in a URL fragment which is considered less secure than using e.g. the Authorization Code flow.
As a thumb rule never reuse keys, this will bring additional security in the designed system in case of key capture
You can send different access token when requested after proper authentication and also send refresh token along your access token.
Once your access token expires, you should inform user about that and user should re-request for new access token providing one-time-use refresh token previously provided to them skipping need for re-authentication, and you should provide new access token and refresh token.
To resist attack with fake refresh token, you should blacklist them along with their originating IP after few warnings.
PS: Never use predictable tokens. Atleast make it extremely difficult to brute force attacks by using totally random, long alpha-numeric strings. I would suggest bin2hex(openssl_random_pseudo_bytes(512)), if you are using php.

OAuth Google - Token refresh

Apologies for typos if any on my phone. We have been trying to put together a solid integration for several providers and aside from Twitter and their non existent email address (oh "good bye" unique key) we have Google with their extremely short token lifetime.
For now we resorted to performing a fake refresh by pushing user through flow on clientside in js.
How would one go about refreshing token without pushing user through the oauth flow without having Offline Access accessType? As refresh tokens are only valid for this accessType.
If i am missing a trick please let me know! All the social providers seem to follow different approaches as expiry does not seem to be exactly specified anywhere so in some cases it is a unixtime stamp some it is a negative integer in seconds relative to now (im guessing it has to be based on UTC or that wont work) and ive seen some that provide expiry as a unix timestamp. Damn was there no RFC for OAuth 2??
Any insights appreciated. Thank you.
Update
Apologies for the lack of clarity. Everything works, it's just Googles OAuth tokens are so shortlived. It's not a showstopper, it's just not ideal that we have to refresh Google's OAuth tokens with JS or use 'accessType' offline.
You don't say anything in your question about the specific OAuth flow that your app is using, so it's hard to provide a solid answer.
Two approaches tha spring to mind:-
If you're doing client JavaScript auth, then you can set immediate=true to the "refresh" is done without any user UI.
You can do the offline bit which wins you a refresh token. You could store that on a server and use it to generate access tokens as needed.

Determining When to Refresh Access to Asana API

When I do the initial authentication to the Asana API with OAuth, it gives me a refresh_token as well as an expires_in of 3600 ms (1 hour).
What is the typical way of determining whether my app will need to use the refresh_token to get a new access_token?
I can think of two options:
Watch for an authentication error and then request a new access_token.
Store the date/time from now until 1 hour from now. Then with each API request, check the date/time to see if that time has already passed, and if so, request a new access_token.
Is there a better way than one of these two options? I don't see a recommendation from Asana in their OAuth documentation.
Thanks!
(I work at Asana.)
Great question! Both of your ideas are quite reasonable and should work - pick whichever is easiest / makes sense for your implementation. #1 is a little more robust in case there is skew with the timing, but if you just add some padding (be sure to request the token 1-2 minutes before expiration) then #2 should work just fine.
Note that it is always possible for the user to revoke the token, in which case when you go to get a new token the request will fail.
This seems like a good thing for us to recommend in the documentation, and possibly even add an automatic mechanism for in our client libraries.

How should I store a 3rd party API authentication token in a Rails app?

I am looking at using Savon to consume a SOAP API. One of the requirements of this particular API is that an authentication token be supplied in each request to the API. That is, apart from the request that returns the authentication token itself. That call just needs a username and password. The token expires after 20mins of inactivity.
My question is, what is the best practice for storing this token? It's surely not advisable to make two requests every time, one for the token and one for the actual request?
I was considering storing it in a session variable but this would mean generating a new token for each visitor, which I presume is not necessary. However, it would mean I could set a 20 minute expiry on it very easily though.
If I store it in the database, how would I know whether or not it will have expired before making the call to the API, without a lot of extra logic?
Or, should I store it in the database and simply make a background call to the API every few minutes to ensure the token never expires?
Or am I barking up completely the wrong tree?!
Thanks for any advice.

Resources