No recibir el token de actualización de Google OAuth
Quiero obtener el token de acceso de Google. La API de Google dice que para obtener el token de acceso, envíe el código y otros parámetros a la página de generación del token y la respuesta será un objeto JSON como:
{
"access_token" : "ya29.AHES6ZTtm7SuokEB-RGtbBty9IIlNiP9-eNMMQKtXdMP3sfjL1Fc",
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : "1/HKSmLFXzqP0leUihZp2xUt3-5wkU7Gmu2Os_eBnzw74"
}
Sin embargo, no recibo el token de actualización. La respuesta en mi caso es:
{
"access_token" : "ya29.sddsdsdsdsds_h9v_nF0IR7XcwDK8XFB2EbvtxmgvB-4oZ8oU",
"token_type" : "Bearer",
"expires_in" : 3600
}
Sólo se refresh_token
proporciona con la primera autorización del usuario. Las autorizaciones posteriores, como las que realiza mientras prueba una integración OAuth2, no devolverán el refresh_token
permiso. :)
- Vaya a la página que muestra las aplicaciones con acceso a su cuenta: https://myaccount.google.com/u/0/permissions .
- En el menú Aplicaciones de terceros, elija su aplicación.
- Haga clic en Eliminar acceso y luego haga clic en Aceptar para confirmar.
- La próxima solicitud de OAuth2 que realice devolverá un
refresh_token
(siempre que también incluya el parámetro de consulta 'access_type=offline'.
Alternativamente, puede agregar los parámetros de consulta a la redirección de OAuth (consulte la página OAuth 2.0 para aplicaciones de servidor webprompt=consent&access_type=offline
de Google ).
Esto solicitará al usuario que autorice la aplicación nuevamente y siempre devolverá un archivo refresh_token
.
Para obtener el token de actualización, debe agregar ambos approval_prompt=force
y, access_type="offline"
si está utilizando el cliente Java proporcionado por Google, se verá así:
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT, JSON_FACTORY, getClientSecrets(), scopes)
.build();
AuthorizationCodeRequestUrl authorizationUrl =
flow.newAuthorizationUrl().setRedirectUri(callBackUrl)
.setApprovalPrompt("force")
.setAccessType("offline");
Me gustaría agregar un poco más de información sobre este tema para aquellas almas frustradas que enfrentan este problema. La clave para obtener un token de actualización para una aplicación fuera de línea es asegurarse de presentar la pantalla de consentimiento . Solo se refresh_token
devuelve inmediatamente después de que un usuario otorga autorización haciendo clic en "Permitir".
El problema surgió para mí (y sospecho que para muchos otros) después de haber estado realizando algunas pruebas en un entorno de desarrollo y, por lo tanto, ya había autorizado mi aplicación en una cuenta determinada. Luego pasé a producción e intenté autenticarme nuevamente usando una cuenta que ya estaba autorizada. En este caso, la pantalla de consentimiento no volverá a aparecer y la API no devolverá un nuevo token de actualización . Para que esto funcione, debe forzar que la pantalla de consentimiento vuelva a aparecer:
prompt=consent
o
approval_prompt=force
Cualquiera de los dos funcionará, pero no debes usar ambos. A partir de 2021, recomendaría su usoprompt=consent
, ya que reemplaza el parámetro anterior approval_prompt
y, en algunas versiones de la API, este último estaba roto ( https://github.com/googleapis/oauth2client/issues/453 ). Además, prompt
hay una lista delimitada por espacios para que puedas configurarla prompt=select_account%20consent
si quieres ambas cosas.
Por supuesto también necesitas:
access_type=offline
Lectura adicional:
- Documentos: https://developers.google.com/identity/protocols/oauth2/web-server#request-parameter-prompt
- Documentos: https://developers.google.com/identity/protocols/oauth2/openid-connect#re-consent
- Discusión sobre este problema: https://github.com/googleapis/google-api-python-client/issues/213
Busqué durante una larga noche y esto está funcionando:
User-example.php modificado desde admin-sdk
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
$authUrl = $client->createAuthUrl();
echo "<a class='login' href='" . $authUrl . "'>Connect Me!</a>";
luego obtienes el código en la URL de redireccionamiento y te autentificas con el código y obtienes el token de actualización.
$client()->authenticate($_GET['code']);
echo $client()->getRefreshToken();
Deberías guardarlo ahora ;)
Cuando su clave de acceso se agote, simplemente hágalo
$client->refreshToken($theRefreshTokenYouHadStored);
Esto me ha causado cierta confusión, así que pensé en compartir lo que he aprendido de la manera más difícil:
Cuando solicita acceso utilizando los parámetros access_type=offline
y approval_prompt=force
, debería recibir un token de acceso y un token de actualización . El token de acceso caduca poco después de recibirlo y deberá actualizarlo.
Realizó correctamente la solicitud para obtener un nuevo token de acceso y recibió la respuesta que tiene su nuevo token de acceso . También me confundió el hecho de que no recibí un nuevo token de actualización . Sin embargo, así es como debe ser, ya que puedes usar el mismo token de actualización una y otra vez.
Creo que algunas de las otras respuestas suponen que deseaba obtener un nuevo token de actualización por algún motivo y sugirieron que volviera a autorizar al usuario, pero en realidad no es necesario, ya que el token de actualización que tiene funcionará hasta revocada por el usuario.