Refreshing user facebook tokens

I have an application in rails which is heavily based on facebook oauth2. At a glance - user signs in with FB connect and can list it's pages (and do some stuff with that data but that's not important right now. Let's just focus on signing-in and getting pages list).

After a sign-in, i'm saving user

access_token

and

expires_at

in the db. Then, each time i need to make a request to facebook api as a user (to obtain his pages list), i'm checking if expires_at is not past and if it is, i'm renewing user token using a following snippet:

def refresh_facebook_token
# Checks the saved expiry time against the current time
return unless facebook_token_expired?

# Get the new token
new_token = facebook_oauth.exchange_access_token_info(
old_access_token)

# Save the new token and its expiry over the old one
self.facebook_auth = {
uid: uid,
access_token: new_token['access_token'],
expires_at: Time.now + new_token['expires'].to_i
}
save
end

This works most of the times but, from time to time, my code throws:

type: OAuthException, code: 190, error_subcode: 460, message: Error validating access token: Session does not match current stored session. This may be because the user changed the password since the time the session was created or Facebook has changed the session for security reasons. [HTTP 400]

in line with

exchange_access_token_info

.

That error is thrown fo my own user and i can say that i didn't changed the password so i'm not sure what's that caused by nor how can i deal with refreshing the tokens by backend in a bullet-proof way.

First of all, I would recommend you go through this link and decide which configuration makes sense for your application - using short-lived or long-lived or what.

Now, am not too sure but I think that you are considering the method exchange_access_token_info as the token refresher. If so, this is NOT the case! Once a token is expired, it's useless.
exchange_access_token_info method simply takes the short-lived token (which is currently active) and convert it into the long-lived token using app id and secret.

Just understand that-

The user access token cannot be extended infinitely again and again without any user's interaction with your app for 60 days.

So the flow is very simple-

you get the short-lived token when user authenticates your app (user engagement on front-end)