All you need is accessType: 'offline' and you'll get the refreshToken on first login.
You don't need approvalPrompt or prompt in the request.
Note this only works on first login if you don't capture and save the refreshToken and associate it with a user account on first login you can't easily get it again.
If you didn't capture it the first time someone logs in, then you have two options:
- If a user logs in and you don't have a refreshToken for them, you can immediately forceably log them out (e.g. by expiring their session in your app) and tell them to go to https://myaccount.google.com/permissions and revoke access to your application then just sign in again.
When they sign in again they will get the same prompt for access they got on first login and you will get the refreshToken on that first new login. Just be sure to have a method in your callback in Passport to save the refreshToken to their user profile in your database.
You can then use the refreshToken to request a rotating accessToken whenever you need to call a Google API.
- You could also add both
accessType: 'offline' and prompt: 'consent' options, but this is probably not what you want in a web based application.
Using these will prompt every user to approve access to your app every time they sign in. Despite the name, approvalPrompt does not enforce this, at least not in the current version of the API (judging by the number of people mentioning it and how often oAuth APIs change it's entirely possible this behavior used to be different).
This isn't a great approach for web based apps as it's not a great user experience but might be useful for development/debugging.
More about the second option:
This option is intended for scenarios such as mobile or desktop apps where the tokens will persist locally (not in a browser, where they are much more likely to be cleared when cache is cleared or they naturally expire).
Google limit how many refresh tokens they will issue for a user on an application (and they will invalidate the oldest tokens automatically and silently) so it's generally a bad idea to use this approach for a web app, as users might find they end up getting signed out of other browser sessions.