Hi all,

When using OAuth2 with PKCE for user access, I’m getting inconsistent errors from refresh tokens which is incredibly frustrating and confusing.

All users of my app have granted the offline.access scope, and when attempting to gain a new access token via the refresh token, every now and then the API will return an error saying that the refresh token is invalid - yet if I keep trying to refresh it, it eventually will refresh the access token, though it can take hours or longer. There’s nothing in my code that would be causing this - I have checked the passed value of the refresh token every time this error has occurred, and every time the value is correct.

This error is impossible to distinguish from a user who has revoked app permissions, making it impossible for me to avoid my app continually sending auth requests for a revoked user, as I cannot know if they actually revoked the application, or what is going on with the refresh token.

2 Likes

I think this might be the same issue I’m experiencing: Refresh token expiring (with offline.access scope) - #9 by dewey

Do you by any chance have different environments where in one of them the token expires quickly while it works in the other one? That might explain the inconsistent errors.

I don’t have different environments, but what I do notice is that for a given set of users it seems to fail consistently and constantly, no matter how long the refresh token has been around for (including for users who I know did not revoke their access to the application).

Sorry for the late reply, been busy >_<

my experience, I detect expired token by calling GET /2/users/me endpoint, if error it will trigger refresh token request, then save new token and new refresh code. However, due to code error after the token refresh request and before saving the new token, the new refresh code is not saved. As a result, the next refresh token request failed with the error message “refresh code is invalid”. To prevent this from happening then I detected refresh error, so if the first request to the GET /2/users/me endpoint fails it will trigger a refresh, then if the refresh fails it will trigger the deletion of the credential data in the database, and the client will re-authorize from the beginning. So far, in the use of internal tests, there are no problems, or triggers to delete data, meaning that the refresh token was successful.

It might be a little different in your case, because this happens at the beginning of writing code, whereas you mention that it doesn’t happen to all your clients (if I understand correctly). But maybe you can use a credential wipe solution while this issue is not resolved.

“if error it will refresh token” - how? You can’t refresh your access token if the refresh token is seen as invalid… unless I missed something about what you mean here.

Credential wipe solution isn’t helpful for me (and probably not for almost all other applications either). The whole point of having a refresh token is to use the offline.access scope - i.e. the user wants to authorise an application to act on their behalf without having to keep logging in. Wiping the credentials means the app won’t work for the user until they sign in again, and they won’t know it isn’t working either.

First I make a request to the endpoint, if it fails it will trigger a refreshtoken request code. (Sorry about my english)

Yes I realize that, it’s really troublesome but this is only I use when experimenting, and till now there are two clients as experiment, multiple times triggering refreshtoken request and success, no data wipe has occurred.

What I haven’t tried is trying to revoke permissions from the client side then trying to run the app, I’ll update later here

No problem ^^ I assume you mean here that if the access token fails, then it tries to refresh the token, which will also fail if the API thinks the refresh token is invalid.

It’s hard to know what this means without the above - you’re getting success when trying to use a previous invalid refresh token, or something else?

this is the flow where we assume that there will be no problem requesting a refresh.

No , the only “invalid refresh token” happens is when I fail to save the new refresh token, whereas the actual refresh request was successful when it failed to save the new refresh code.

A bit complicated to explain :sob:

1 Like

Yeah, we would normally assume there is no problem requesting a refresh.

That sounds more like a code problem on your side, no? Unless you mean that the API is not giving you the new refresh token?

In theory, so long as you always save the new refresh token without error, then there shouldn’t be a problem.

The problem I’m having is that I’m getting the new refresh token successfully on a request, but sometimes the refresh token seems to invalidate itself - ending any ability to perform actions for a user unless they log in again.

yeah, right

Exactly

that’s what I’m trying to say, I’m telling the experience of failure to save the refresh code will cause failure in the future, , is it possible that you missed the code that causes the occasional failure to save the new refresh code?

I’m certain I didn’t miss it - I have no database errors, I checked that the new tokens are being updated correctly every time, etc. I’m also certain it wasn’t due to user revoking permissions as one of the affected users was my own account.

Yes, this is also my experience. It seems that somehow it happens that sometimes the refresh token just isn’t valid as long as it should even if the refresh token code is only used once and the new one is always stored without issues.

It’s hard to debug so I wrote a script to refresh a token every h hours so I can somehow try to see a pattern. I ran this with a 60 min refresh interval over the past days and never had any issues. I’m going to try 24h interval now (one refresh every 24h) to see if there’s an issue.

Maybe it’s useful for your experiments too, let me know if you have any questions.

My assumption is that a refresh code with the offline scope should basically be valid for a few months so even if my app code would fail to refresh the token of all my users it would still work.

This is exactly main main use case and worry too, if I update my code base and use the new tokens and something happens I’m basically losing all my users (especially because of the new “feature” that you won’t see your user’s email address so I can’t even contact them to prompt them to re-login).

3 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.