Keywords: Google API | OAuth 2.0 | Refresh Token | Access Token | Authorization Flow
Abstract: This article provides a comprehensive analysis of refresh token acquisition failures in Google API OAuth 2.0 authorization flow. Based on Q&A data and official documentation, it explains the correct usage of access_type=offline parameter and emphasizes the necessity of prompt=consent parameter as a replacement for the deprecated approval_prompt=force. The article includes complete code examples and authorization flow explanations to help developers understand token lifecycle management and user re-authorization mechanisms.
Problem Background and Symptom Analysis
In the Google API OAuth 2.0 authorization flow, many developers encounter issues with obtaining refresh tokens. The typical symptom is: although access_type=offline parameter is set according to tutorials, only access token, token type, ID token, and expiration time are received during authorization code exchange, while the crucial refresh token is missing.
Core Solution
Through in-depth research and community validation, it has been discovered that the prompt=consent parameter needs to be added to the authorization request URL. This parameter forces the display of user consent interface, even if the same scopes were previously authorized.
Correct authorization URL construction example:
echo "<a href='https://accounts.google.com/o/oauth2/auth?"
. "access_type=offline&prompt=consent&client_id=123345555.apps.googleusercontent.com& "
. "scope=https://www.googleapis.com/auth/calendar+https://www.googleapis.com/auth/plus.me&response_type=code& "
. "redirect_uri=http://www.sample.com/sample.php&state=/profile'>Google</a>";
Parameter Evolution History
The early solution used the approval_prompt=force parameter, but this parameter is no longer effective after Google OAuth 2.0 endpoint updates. According to relevant GitHub discussions and official changes, prompt=consent has become the new standard solution.
Technical Principle Deep Analysis
According to the offline access section of Google's official documentation, when an application obtains a refresh token for the first time, subsequent authorization requests for the same scopes will not return new refresh tokens by default. This is a security-conscious design to prevent unnecessary token refresh.
The refresh token acquisition mechanism follows these rules:
- During initial authorization, if
access_type=offlineis set, Google returns a refresh token - In subsequent authorization requests, even with
access_type=offlineset, no new refresh token is returned - New refresh tokens are only returned when users explicitly consent again (forced via
prompt=consent)
Complete OAuth 2.0 Authorization Flow
The complete Google OAuth 2.0 authorization flow consists of five basic steps:
- Obtain OAuth 2.0 Credentials: Get client ID and client secret from Google API Console
- Obtain Access Token: Request access token from Google Authorization Server, including scope parameters to control access range
- Check Authorization Scope: Verify if the access scope granted by users meets application requirements
- Send Access Token to API: Include access token in HTTP Authorization header when calling API
- Refresh Access Token: Use refresh token to obtain new access token when current one expires
Code Implementation Example
The following complete PHP implementation code demonstrates how to correctly obtain responses containing refresh tokens:
// Construct authorization request URL
$auth_url = 'https://accounts.google.com/o/oauth2/auth?'
. 'access_type=offline&'
. 'prompt=consent&'
. 'client_id=' . urlencode($client_id) . '&'
. 'scope=' . urlencode('https://www.googleapis.com/auth/calendar '
. 'https://www.googleapis.com/auth/plus.me') . '&'
. 'response_type=code&'
. 'redirect_uri=' . urlencode($redirect_uri) . '&'
. 'state=' . urlencode('/profile');
// Exchange authorization code for tokens
$fields = array(
'code' => urlencode($auth_code),
'client_id' => urlencode($client_id),
'client_secret' => urlencode($client_secret),
'redirect_uri' => urlencode($redirect_uri),
'grant_type' => 'authorization_code'
);
// Send POST request
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://oauth2.googleapis.com/token');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
// Parse response
$token_data = json_decode($response, true);
if (isset($token_data['refresh_token'])) {
// Successfully obtained refresh token
$refresh_token = $token_data['refresh_token'];
$access_token = $token_data['access_token'];
// Securely store refresh token for future use
}
Token Lifecycle Management
Access tokens have limited lifetimes, typically 1 hour. Refresh tokens allow applications to obtain new access tokens after expiration without requiring user re-authorization.
Refresh token usage example:
// Use refresh token to obtain new access token
$refresh_fields = array(
'refresh_token' => $refresh_token,
'client_id' => urlencode($client_id),
'client_secret' => urlencode($client_secret),
'grant_type' => 'refresh_token'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://oauth2.googleapis.com/token');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($refresh_fields));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$new_token_response = curl_exec($ch);
curl_close($ch);
Best Practices and Considerations
When implementing Google OAuth 2.0, the following best practices should be considered:
- Secure Refresh Token Storage: Refresh tokens should be stored in secure locations, such as encrypted databases or secure file systems
- Handle Token Expiration: Applications should gracefully handle access token expiration by automatically using refresh tokens to obtain new ones
- Error Handling: Implement comprehensive error handling mechanisms for authorization failures, token refresh failures, etc.
- Scope Management: Adopt incremental authorization approach, requesting corresponding scope permissions only when needed
- Token Limits: Be aware of the limit of 100 refresh tokens per Google Account per client ID
Common Issue Troubleshooting
If issues persist during implementation, check the following aspects:
- Confirm
prompt=consentparameter is correctly added to authorization URL - Verify correctness of client ID and client secret
- Check if redirect URI matches configuration in API Console
- Confirm requested scopes match APIs enabled in API Console
- Review OAuth consent screen configuration in Google Cloud Console
By properly understanding OAuth 2.0 authorization mechanisms and following the above best practices, developers can successfully implement Google API integrations with refresh token functionality, ensuring applications can stably access user data over the long term.