According to Google's docs on OAuth, the server application gets refresh_token
from Google (on exchanging the auth code) only if the original redirection request to Google contains the param access_type
with value offline
(documentation link).
But this is only for the first time a user authenticates with your app. If for some reason your flow takes the user through the authentication flow again without having changed anything (user's Google account, permissions required, etc. Haven't tested with changed permissions yet but definitely happens when permissions also remain the same) then when you exchange auth code for tokens from Google, the Google servers don't return the refresh_token
this second time.
This is based on anecdotal observation, and I couldn't find any such mention in their documentation. An answer on Stack Overflow confirmed for me that it wasn't something misconfigured on my end 😅.
A "solution" for this could be to always specify the param prompt
with a value of consent
in the original redirect request where we send user to Google's flow.