We are integrating on our application the Office 365 functionality throught MSGraph rest api and we are currently getting trouble with the validation of Refresh Tokens, this is the response error code from the server on a invalid petition:
"error":"invalid_grant","error_description":"AADSTS70002: Error
validating credentials. AADSTS70008: The refresh token has expired
due to inactivity.??The token was issued on
2016-04-27T11:44:49.4826901Z and was inactive for 14.00:00:00.
This is annoying because we need the users to aquire their credentials again logging in on Microsoft servers.
Is there any option to avoid Refresh token being invalidated due to inactivity? Or to make longer this expiration?
Refresh tokens have a finite lifetime. If a new token (and refresh token) isn't requested before that time they will expire. Once this happens the user must re-authenticate.
If you need to have perpetual access to the account, you will need to manually refresh the token periodically. You may want to look at this article. It covers the basics of how v2 Endpoint works (and the various token lifetimes).
In most of my implementations I use a queue to handling refreshing tokens. I queue each token to be refreshed at 10 days. If it fails I resubmit to the queue. If it is still failing at day 12 I email the user to inform them there was an issue and they will need to re-authenticate.
UPDATE
Refresh token lifetime was recently changed to until-revoked. You can read about the change here
This is general OAuth (not AAD-specific): obtaining an access token is a 2-step process. The first step is to obtain an auth code which requires the user to authenticate. The second step is to redeem an access token and a refresh token from the auth code. This second step is purely programmatic, i.e. the user need not be present. The app can keep repeating the second step, i.e. redeeming a new access token and a new refresh token from the latest refresh token without the user even know about it.
Your app should schedule frequent 'refreshes' of the refresh token. You can do this at any time while the app is running.
If the user doesn't use the app for an extended period of time, like about 2 weeks (I believe), the refresh token would naturally expire. If you want to avoid that, you'll have to schedule a dedicated job to refresh the token.
Zlatko
Related
When I'm trying to activate a service account using the gcloud CLI command.
gcloud auth activate-service-account --key-file key.json
I am getting the below error since yesterday. I was able to create a service account with the same command 2 months ago and the service account was created at that time.
ERROR: (gcloud.auth.activate-service-account) There was a problem refreshing your current auth tokens: ('invalid_grant: Invalid JWT Signature.', {'error': 'invalid_grant', 'error_description': 'Invalid JWT Signature.'})
What is the issue here?
I've come across this answer which might be helpful on your case. 2 common causes were:
Your server’s clock is not in sync with NTP.
Solution: Check the server time. If it's incorrect, fix it.
The refresh token limit has been exceeded.
Solution: Nothing you can do - they can't have more refresh tokens in use.
Applications can request multiple refresh tokens. For example, this is useful in situations where a user wants to install an application on multiple machines. In this case, two refresh tokens are required, one for each installation. When the number of refresh tokens exceeds the limit, older tokens become invalid. If the application attempts to use an invalidated refresh token, an invalid_grant error response is returned.
The limit for each unique pair of OAuth 2.0 client and is 50 refresh tokens (note that this limit is subject to change). If the application continues to request refresh tokens for the same Client/Account pair, once the 26th token is issued, the 1st refresh token that was previously issued will become invalid. The 27th requested refresh token would invalidate the 2nd previously issued token and so on.
Just to add, please verify the validity of the service account key and try to setup the environment variable again.
After googling we came to know that invalid_grant which means refresh token is invalid.
Link to google oauth doc
We don't have any of these issues mentioned by google. Is this error related to something else rather than a refresh token.
More Info
We have access to read, write spreadsheet and send gmail
We fetch an access token for each request
Any help would be appreciated.
We're already in production and verified by google
Without seeing the full error message that being
Invalid_grant {Message here}
It is hard to help but from my experience is most often caused by one of the following.
Refresh token expire, app not in production.
There are serval reasons why a refresh token can expire the most common one currently is as follows.
A Google Cloud Platform project with an OAuth consent screen configured for an
external user type and a publishing status of "Testing" is issued a refresh token expiring in 7 days.
The fix is to go to google developer console on the consent screen and set your application to production, then your refresh token will stop expiring.
invalid_grant: Invalid JWT
{ “error”: “invalid_grant”, “error_description”: “Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values and use a clock with skew to account for clock differences between systems.” }
Your server’s clock is not in sync with NTP. (Solution: check the server time if its incorrect fix it. )
invalid_grant: Code was already redeemed
Means that you are taking an authentication code that has already been used and trying to get another access token / refresh token for it. Authentication code can only be used once and they do expire so they need to be used quickly.
Invalid_grant: bad request
Normally means that the client id and secrete you are using to refresh the access token. Was not the one that was use to create the refresh token you are using.
Always store most recent refresh token.
Remember to always store the most recent refresh token. You can only have 50 out standing refresh tokens for a single user and the oldest one will expire. Depending upon the language you are using a new refresh token may be returned to you upon a refresh of the access token. Also if you request consent of the user more then once you will get a different refresh token.
User revoked access
If the user revoked your access in their google account, your refresh token will no longer work.
user changed password with gmail scope.
If your refresh token was created with a gmail scope and the user changed their password. your refresh token will be expired.
Links
Oauth2 Rfc docs for invalid_grant error rfc6749
invalid_grant
The provided authorization grant (e.g., authorization
code, resource owner credentials) or refresh token is
invalid, expired, revoked, does not match the redirection
URI used in the authorization request, or was issued to
another client.
Conceptually, I really like JWT as it is in line with the statelessness of REST etc (no state saved server-side, all relevant data is contained in the token).
What I am unsure about: how would you handle token expiry when not connected (ie, a "remember me" functionality)?
There's an emerging coverage of JWT on the web, but I couldn't find anyone that answered the expiry question yet.
Clarification: I am not asking how to handle a token soon-to-expire, but what to do when a token has already expired (user closed website/app for a while). The simplest solution that comes to my mind is caching the user's credentials, which is rather insecure.
There isn't a black and white answer to the given problem of how to implement the remember-me functionality theoretical wise. Lots of theoretical arguments are given on why something should not be done, while at the same time there is no clear answer given to the problem as for how it should practically be done.
Remember-me implicitly comes with the problem that you need a longer time window of token expiration, there is just no way around this. The most secure way is to have the user login regularly given brief expiry; nobody practically likes this though, so a tradeoff is made where theoretical secure perfection is weighed against practical measures.
The way this tradeoff works is by patching the imperfections that come with having a long expiry for a token. But make no mistake about it, you will need a jwt / cookie with long expiry (whether you use two tokens, implement some secondary refreshing mechanism or whatever, at the end you run into the same problem)!
Based on articles I've read on how others did it, this is how it's done.
The way I will implement this is by offering a 3-month expiry on a jwt stored in an httpOnly / secure cookie when the user checks remember-me.
On logout just clear the cookie.
Obviously protect using https / CSRF measures on top.
If you don't agree with it, stop fussing and offer an alternative solution - which there clearly isn't from the infinite number of discussions I've read on it.
If there were a straightforward solution to the problem, there probably wouldn't be so many discussions about it in the first place.
Edit:
You can use a refresh token mechanism, but it only works if you verify the time intervals when the refresh token gets used. For example, depending on the lifetime of the access token, you can govern how often you allow a user to refresh the token. If the intervals show suspicious activity, you should revoke both the tokens for all clients.
The problem revolves around the idea that either access token or refresh token would theoretically be stolen. So merely having a refreshing mechanism without additional security is essentially useless. If you can steal an access token, you can steal a refresh token too.
I am not so sure if I follow but I will write what I think.
Imagine the token as a hotel card, you pay in advance for 5 days (remember me set to expire on 5 days). I can enter the building, garage, room, etc. within those 5 days, after those 5 days, it won't work anymore.
What to do when token has already expired? Nothing at all.
Imagine I pay those 5 days and meh, I had an urgency and I go back home (with the card on the pocket). The hotel doesn't care at all, when the 5 days pass, the card is just an useless piece of plastic and if you try to use it on the hotel, it will do nothing.
So back to web development. If you offer a remember me service, you can put an expiry date to let's say 7 days. As long as the user has the token, he can access the service without any problem. If he loses the token, he needs to login again. If he uses the token and it have expired, he will need to login again too.
If he login, he gets a token for 7 days, if he doesn't use it anymore and after 20 days he comes again, he would need to login again, the server will just decline your petitions until you do so.
What I would do if you use something like angular on the frontend is to check the token validation on startup so you can have a nice user experience.
What I don't understand about your question is de caching thing though.
In addition to #Jesus answer, you can think about implementing a refresh token system: https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/
In the hotel-example, your hotel-card (access-token) would be invalid after time X, but at the reception you can use your passport (refresh-token) to get a new hotel card again.
You could store the refresh token in the database with additional data about the device the user is using, allowing him to disable the device in case it gets stolen.
Example:
first correct client login: Create a refresh token which is valid forever (until it gets deleted or invalidated)
store refresh token in database
return access token (JWT) with expiration time to client ( this token gets not stored in database)
for the next request, the client sends the access token
Now Check if the access token is expired:
5.1 Access Token not expired, all okay
5.2 Access Token expired, check if there is a refresh token in database
5.2.1 Refresh Token is in database, return new Access Token
5.2.2 No Refresh Token in database, return 401 / logout, User has to login again
Hope this helps.
You need to persist the JWT on the client so that it’s available across page loads, the most secure strategy is an HTTPS-only cookie. This will send the JWT to your server on every request and the server can check the validity of the token and reject it if it's expired. How you handle the expiration is dependent on the type of web app you have.
For a single-page application (e.g. Angular.js apps) you would want to structure the application so that it makes an initial request of the server before it bootstraps the rest of the application. If the server sees that the JWT in this request is expired it would issue a 401 response. You application would respond to this response by rendering a login form. Otherwise it would continue with the assumption that the JWT is valid and can be used to access the required resources. If, at any time, the app sees a 401 it should bring the user back to the login form.
For traditional web apps that render their pages on the server: for any request that has an expired JWT (as read from the cookie) the server should issue a 302 redirect to a login form.
I think what you are asking is how to invalidate a JWT server side for long expiry tokens (e.g. "remember me" functionality)?
I ran into this issue myself recently and ended up using a unique user secret to invalidate the token, when the user attempts to validate a token that was produced with an old secret it will fail. The username can be found in the decoded JWT pre verification.
You could probably even use the users password salt for this, that way any current JWT's would be invalidated when a user changes their password (assuming you also change the salt at the same time), this may be problematic though as the password hash and JWT's would become tightly coupled
I can think of one way, but it is not really defined the standard.
What about adding another kind of expiration date with different lifespan to the claims? With two claims, we can treat the shorter one of it as the resource access expiration date, and the longer one as the refresh expiration date, e.g.
{
"iat": /* current time */,
"bbf": /* current time + 1 hour -- expired means no resource access */
"exp": /* current time + 1 week -- expired means cannot refresh */
}
(Note: I use bbf for the shorter expiration date. No specific reason, just because it has 3 characters in length.)
So with "remember me" checked, when the user reconnects, he can use the same token to request for a new one, but not to access the resource. With this, all relevant data is contained within the token -- no extra token required.
And lastly, when "remember me" not checked, just use the same lifespan for bbf and exp.
The situation is still unclear for me – After July 5th 2012, will desktop application be able to have access to Facebook data if user, associated with access token, logged out from Facebook?
Are talking here about TOTAL deletion of offline access AT ALL or just limitation for offline access by 60 days?
Document - https://developers.facebook.com/roadmap/offline-access-removal/ doesn’t give clear answer (IMHO). Quote: “Once the migration setting has been enabled, Desktop applications will automatically get user access_tokens returned that have the longer expiration time. However, there is no way to get a long-lived user access_token without having the user login to your app again.”
As of April 30 I’m able to request access token WITH ‘offline_access’ permission for desktop application (using URL: https://graph.facebook.com/oauth/authorize?client_id=APPLICATION_ID&redirect_uri=http://www.facebook.com/connect/login_success.html&scope=manage_pages,read_stream,publish_stream,offline_access
) . And everything work fine. Even if user logged out. In spite of “Remove offline_access permission” was enabled for the application.
Your answers will be very much appreciated.
Just completed a patch to accommodate these changes. At least in my experience, we were working within a web app where renewing the access tokens was as simple as changing everything over to the Javascript SDK and relying on the browser's login state. This seemed a much more logical approach than cross-checking a server-side saved long-expiry access token with every action to see if it was still good.
Essentially, what is going to happen for desktop implementations is the access tokens will be longer-lived by default, but still require the renewal at the end of the sixty day period. You should have logic in your app that will check that validity of the access token with facebook before taking action with it (or just try and fail with a prompt) and then prompt the user to login and revalidate if the access_token has expired. So long as this logic is in place the access tokens that expire will trigger re-validation.
If your app receives short-expiry access tokens...
If you would like to refresh a still valid long-lived access_token, you will have to get a new short-lived user access_token first and then call the same endpoint below. The returned access_token will have a fresh long-lived expiration time, however, the access_token itself may or may not be the same as the previously granted long-lived access_token.
Short-lived access tokens, the kind that only last for a session until logout, are going to need to be converted to the sixty-day, long-expiry access tokens using the endpoint documented in that article. Desktop apps configured to the new setting will receive these kind by default, but these will still need to be regenerated with a new login after 60 days.
I agree that this is a lot clumsier to implement, especially for desktop apps, but it is certainly a lot more secure from facebook's standpoint. If you start to think of the access token as a transient rather than permanent access credential and start changing your logic to check validity via curl or some other http post mechanism, rather than referencing your database, you'll have a much easier time with the adjustment. Don't allow your architecture to assume that the presence of a saved access token guarantees access, and be sure to cross check them over to the facebook endpoints and prompt for re-login where necessary.
Is there any way to use the graph api to find out when a page access token, or application token will expire?
Update: There is a new API endpoint to access information about an access token. You can find info here: Debugging Access Tokens and Handling Errors
https://graph.facebook.com/debug_token?input_token=INPUT_TOKEN&access_token=ACCESS_TOKEN
input_token: the Access Token to debug
access_token: your App Access Token or a valid User Access Token from a developer of the app.
--
You should try to make sure that you store each token's expiration time along with the access token when you get it. For a page access token, that means storing the expiration time of the user access token. If you would like to manually discover expiration times for tokens you have today, you should use Facebook's Access Token Debugger tool. However, you should not be relying on expiration times alone -- in practice, many tokens will expire much earlier than their expiration time.
Application access tokens will never expire, unless the application secret key is reset.
Page access tokens last up to 60 days (5184000 seconds), but more importantly, they last as long as the user access token that was used to acquire them. So they will be invalidated as soon as the user that you got them from:
logs out of FB.
changes password.
deauthorizes your application.
Basically, when you lose the user's token, you will lose the page's token. Instead, you should retrieve page access tokens once per user access token. If you throw out a user access token, throw out the page token. You should not be trying to store page access tokens for any significant period of time. Instead you should get them as needed and forget them when a user's session dies.
To get a new page access token:
https://graph.facebook.com/PAGEID?fields=access_token&access_token=USER_ACCESS_TOKEN
Access Token Debugger
https://developers.facebook.com/tools/debug/access_token
Does not use the Graph API... but a very useful tool for manual debugging.
There is now an API version of the debugger tool.
See https://developers.facebook.com/docs/authentication/access-token-debug/
I would like to repeat this question for the current version of the API since I've come to a situation when Facebook doc clearly does not describe what is happening:
no expiry dates when requesting a new long-lived token with fb_exchange_token
no expiry dates when requesting debug_token information (expires_at = 0)
it does reply with an expiration date when redirecting the user to the auth page for the first time, but that does not help as I cannot extract the long-lived expiration date nor it will reply with this information for the second time
The debug tool here: https://developers.facebook.com/tools/debug/accesstoken says "Expires: Never".
Try this, it worked with me. Get the token with your app and paste it in the graph explorer as the token to be used for queries. Click on the info a see the expiration date.
example image
I hope it works for you too.
https://developers.facebook.com/docs/facebook-login/access-tokens/expiration-and-extension
From the page above:
Access tokens on the web often have a lifetime of about two hours, but
will automatically be refreshed when required. If you want to use
access tokens for longer-lived web apps, especially server side, you
need to generate a long-lived token. A long-lived token generally
lasts about 60 days.