So, i was reading the docs and i saw the only way to refresh a token is this
oauth2client.on('tokens', (tokens) => {
if (tokens.refresh_token) {
// store the refresh_token in my database!
console.log(tokens.refresh_token);
}
console.log(tokens.access_token);
});
Isn't it inefficient to add an event to every single client? isn't there a better way to manually check the clients access token and refresh it using the refresh token?
@supertiger1234
The refresh_token is only provided on the first authorization from the user. Subsequent authorizations, such as the kind you make while testing an OAuth2 integration, will not return the refresh_token again. :)
access_token is good for one hour. If your access_token is close to be expired or expired already the next time you execute, than your token will be refreshed automatically with the use of refresh_token.
By adding an listener on tokens event merely helps you record the new access_token value locally when it is refreshed automatically.
Does that help you?
Ohhh, so it happens automatically?
Also, what if I wanna use the refresh token from a database? Do I just do setCredentials({access_token: db.accessToken})?
Thanks a lot for the quick reply
Hey! I randomly came across this issue and I actually wanted to ask something very similar to @supertiger1234 asked.
What if I want to save the new token to the database? Using the listener becomes very hard in that matter.
What is your suggestion?
Same issue. I want to ask what's the difference about these two ways:
Way 1: oauth2client.setCredentials({access_token: db.accessToken})
Way 2: oauth2client.setCredentials({refresh_token: db.refreshToken})
According to the docs, I think the way 2 is enough. oauth2client will always refresh access token automatically. I don't need worry about the expiration about access token.
oauth2client.on('tokens', (tokens) => {
//store access_token in your database
console.log(tokens.access_token); // for testing
});
this function "oauth2client.on('tokens')" will only run(automatically), when your previous access_token gets expired.
So inside this function, you can get the latest access_token and store it onto your database.
Storing new access_token is important in order to prevent unnecessary requests for a new access token.
@mrdulin @fabiofcferreira for the use-case where credentials are being stored for a long period of time, and you're relying on the refresh_token.
I would recommend storing both the access_token and the refresh_token, and calling oauth2client.setCredentials with both, e.g.,
oauth2client.setCredentials({refresh_token: db.refreshToken, access_token: db.accessToken})
To make sure you have stored the most recent version of the access_token, you will need to use .on("tokens"). There's some useful examples of this pattern in action here. _(sorry this pattern is a bit of a hassle)_.
I hope this helps clarify 馃憤
I'm going to go ahead and close this issue, since I think @supertiger1234 is unblocked, _but_ if other folks have follow up questions, please don't hesitate to open an additional issue.
@bcoe could you update the link to examples of the pattern for storing the access_token and refresh_token. I can't for the life of me figure out how to store my tokens because I don't have access to the user context when using auth.on('tokens', (tokens) => {}). If not something from the user context, what would you use as the key for storing tokens in a database?
@richardpeng I agree.
@bcoe The tokens event can't access application context. Where should I put this .on("tokens") in application code?
For example, if use express, the context info is attached in req object, like req.user
I think below way is wrong:
app.post('/post', (req, res) => {
auth.on('tokens', async (tokens) => {
const requestingUser = req.user
const user = await db.findByEmail(requestingUser.email)
await db.updateGoogleAccountTokensByUser(user)
})
})
If put auth.on('tokens', (tokens) => {}) on a global environment
auth.on('tokens', (tokens) => {
// Don't know whose tokens
const user = ??
await db.updateGoogleAccountTokensByUser(user)
})
Like @mrdulin and @richardpeng I would also like to have a solution to manage the tokens refresh for several users (stored in a DB).
Also, what is not clear to me, is what happens if the server is shut down and restarted. I guess the automatic refresh works because google-api-nodejs-client keeps in RAM a list of the tokens to be refreshed. But if this is right, then the RAM is lost whenever the server is restarted.
Then, how to prevent all users to re-authenticate again upon every server upgrade?
Can anyone tell me when am I supposed to call this .on('tokens') event? Is it the first time the user authenticates? Because as far as I understand, if this event is called in subsequent API call, it won't return the refresh_token. And I've discovered that in subsequent API call, I only need to attach the refresh token:
oAuth2Client.setCredentials({
refresh_token: REFRESH_TOKEN
})
to get a successful response. The Google API client automatically gets the new access token for me.
@richardpeng @mrdulin have u guys found a solution for your problems. I am currently having the same issue with storing access token using token event since cant get any user data inside of event handler
Most helpful comment
@richardpeng I agree.
@bcoe The
tokensevent can't access application context. Where should I put this.on("tokens")in application code?For example, if use
express, the context info is attached inreqobject, likereq.userI think below way is wrong:
If put
auth.on('tokens', (tokens) => {})on a global environment