-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Access Token Timeout #1
Comments
I personally don't use a recurring task to refresh my tokens, instead I just handle the error when using an expired access token and refresh the token automatically. Let's assume you are using Mongoose and Passport to log the user in with their Google account, and you then set a session token with that user once logged in using var passport = require('passport'),
refresh = require('passport-oauth2-refresh'),
GoogleStrategy = require('passport-google-oauth').Strategy;
passport.serializeUser(function(user, done) {
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
var strategy = new GoogleStrategy({
clientID: GOOGLE_APP_ID,
clientSecret: GOOGLE_APP_SECRET,
callbackURL: "http://www.example.com/auth/google/callback"
},
function(accessToken, refreshToken, profile, done) {
// Store the refresh token with the user profile.
var user = {
email: profile.emails[0],
accessToken: accessToken,
refreshToken: refreshToken
};
User.findOneAndUpdate({ email: user.email }, user, { upsert: true }, function(err, user) {
if (err) { return done(err); }
done(null, user);
});
});
passport.use(strategy);
refresh.use(strategy); When you later need to use the var google = require('googleapis'),
refresh = require('passport-oauth2-refresh');
// This is an express callback.
function getGmailProfile(req, res, next) {
var retries = 2;
var send401Response = function() {
return res.status(401).end();
};
// Get the user's credentials.
User.findById(req.user, function(err, user) {
if(err || !user) { return send401Response(); }
var makeRequest = function() {
retries--;
if(!retries) {
// Couldn't refresh the access token.
return send401Response();
}
// Set the credentials and make the request.
var auth = new google.auth.OAuth2;
auth.setCredentials({
access_token: user.accessToken,
refresh_token: user.refreshToken
});
var gmail = google.gmail('v1');
var request = gmail.users.getProfile({
auth: auth,
userId: 'me'
});
request.then(function(resp) {
// Success! Do something with the response
return res.json(resp);
}, function(reason) {
if(reason.code === 401) {
// Access token expired.
// Try to fetch a new one.
refresh.requestNewAccessToken('google', user.refreshToken, function(err, accessToken) {
if(err || !accessToken) { return send401Response(); }
// Save the new accessToken for future use
user.save({ accessToken: accessToken }, function() {
// Retry the request.
makeRequest();
});
});
} else {
// There was another error, handle it appropriately.
return res.status(reason.code).json(reason.message);
}
});
};
// Make the initial request.
makeRequest();
});
} As you can see, I have used a recursive function in order to automatically refresh the token in the case of a 401 being returned by the GMail API. The recursion is guarded with a retry counter so that any further failures don't cause an infinite loop. |
Ok thanks I understood. In my case it's a third party code that request an accessToken to do something. So I try to keep the code as simple as possible for this part. The function that provide the accessToken keep the last refresh date and refresh the token if it is older than an hour. |
If you want to try and pre-empt the accessToken expiring, you can get the accessToken timeout from the returned var expiry = profile._json.expires_in; See the Google docs for more details on the returned fields. However, I recommend taking the approach above, instead - you will likely need some sort of error handling in case the scheduled task does not refresh the token correctly, and by using the recursive technique, the process will be transparent to the user. |
Anyone have using this with Spotify's web API? |
@jtabone16 I haven't used the Spotify API. Is there a particular problem that you are facing? If so it would be best to create a new issue. |
@fiznool Got everything working finally haha it was an issue I found in my spotify strategy when setting providerIdentifierField. initially, it was set to 'id_str' (used twitter strategy as boilerplate). however, I needed to use 'id' for providerIdentifierField Glad I finally found this bug since it's caused a TON of issues that I couldn't find the source of until now! |
Glad you found the issue!
|
Hi,
I'm using refresh with Google OAuth, how do you handle token timeout ?
Regards
The text was updated successfully, but these errors were encountered: