Obtener el token de actualización de la API de Google

79

No puedo obtener mi token de actualización con mi código. Solo puedo obtener mi token de acceso, tipo de token, etc.He seguido algunos tutoriales, como poner access_type=offlinemi URL de inicio de sesión:

echo "<a href='https://accounts.google.com/o/oauth2/auth?" 
    . "access_type=offline&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>";

y mis campos para obtener el token de acceso:

$fields=array(
    'code'=>  urlencode($authcode),
    'client_id'=> urlencode($clientid),
    'client_secret'=> urlencode($clientsecret),
    'redirect_uri'=> urlencode($redirecturi),
    'grant_type'=> 'authorization_code',
);

pero no puedo obtener refresh_token , solo access_token , token_type , id_token y expires_in .

Robin Carlo Catacutan
fuente
1
/ * verifique este enlace que me funciona @Nobert solution * / stackoverflow.com/questions/10827920/…
Manmeet Khurana

Respuestas:

109

Descubrí agregando esto a tus parámetros de URL

aprobación_prompt = forzar

Actualizar:

Úselo en su access_type=offline&prompt=consentlugar.

approval_prompt=forceya no funciona https://github.com/googleapis/oauth2client/issues/453

Robin Carlo Catacutan
fuente
12
¿Por qué no funciona con Auto? No quiero que los usuarios otorguen permiso siempre. ¿Cómo puedo superar esto?
Harsha MV
6
Porque el token de actualización solo se devuelve la primera vez que se otorga el permiso de la aplicación. Después de eso, todas las solicitudes con approval_prompt=autoya no tienen un refresh_token. Consulte esta respuesta para obtener una explicación más detallada stackoverflow.com/a/10857806/987864
Daan
4
Necesita access_type=offlineen todos los casos cuando desee el refresh_token
Daan
7
Respuesta editada a algo que funciona, ya que esta respuesta es antigua y parece que ya no funciona. Pasé mucho tiempo probando esto, ya que hay varios lugares que dicen usar este método. Finalmente leí la documentación (que debería haber hecho primero) y dice que debes usarla prompt=consent. Referencia: developers.google.com/identity/protocols/…
Goblinlord
9
Tanto @Daan como @Goblinlord tienen razón, luché con esto incluso después de leer sus comentarios. De hecho necesitamos tanto, access_type=offline&prompt=consent. De lo contrario, el refresh_tokenno estará presente.
Noitidart
62

Si puedo ampliar la respuesta del usuario987361 :

Desde la parte de acceso sin conexión de los documentos de OAuth2.0:

Cuando su aplicación recibe un token de actualización, es importante almacenar ese token de actualización para uso futuro. Si su aplicación pierde el token de actualización, deberá volver a solicitar al usuario su consentimiento antes de obtener otro token de actualización. Si necesita volver a solicitar el consentimiento del usuario, incluya el approval_prompt parámetro en la solicitud del código de autorización y establezca el valor en force.

Por lo tanto, cuando ya haya otorgado acceso, las solicitudes posteriores grant_typede authorization_codea no devolverán el refresh_token, incluso si access_typese estableció en offlineen la cadena de consulta de la página de consentimiento.

Como se señala en la cita anterior, con el fin de obtener una nueva refresh_token después de que ya están recibiendo una, tendrá que enviar a la espalda del usuario a través del sistema, lo que puede hacer mediante el establecimiento approval_promptde force.

Salud,

PD: Este cambio también se anunció en una publicación de blog .

langosta mandona
fuente
3
Agregaría que solo necesitaría obtener uno nuevo refresh token si lo pierde o si su usuario revoca su acceso. De lo contrario, puede seguir usando el mismo refresh tokenpara obtener nuevos correos access tokenelectrónicos.
jeteon
1
Tengo un CMS donde diferentes usuarios usan diferentes cuentas de Google para conectarse a la API de análisis. Sin embargo, a veces varios usuarios pueden conectarse utilizando la misma cuenta corporativa de Google, pero cada uno desea acceder a una cuenta de Analytics diferente. Solo el primero recibe el token de actualización, mientras que todos los demás no lo hacen y, por lo tanto, deben volver a conectarse cada hora. ¿No hay alguna manera de obtener el MISMO token de actualización para autenticaciones posteriores en lugar de solo el access_token que caduca en una hora?
SsjCosty
Si. Simplemente hazlo. Cuando envíe la solicitud, obtendrá un token de acceso y el token de actualización.
bossylobster
¡Estaba luchando para obtener un refresh_token y me iluminaste con la solución! "Por lo tanto, cuando ya haya otorgado acceso, las solicitudes posteriores de un grant_type de authorization_code no devolverán el refresh_token, incluso si access_type se estableció en offline en la cadena de consulta de la página de consentimiento".
Cristiana S. Parada
12

Es lo access_type=offlineque quieres.

Esto devolverá el token de actualización la primera vez que el usuario autorice la aplicación. Las llamadas posteriores no le obligan a volver a aprobar la aplicación ( approval_prompt=force).

Ver más detalles: https://developers.google.com/accounts/docs/OAuth2WebServer#offline

Elliot Coad
fuente
1
Esa página vinculada indica que el cliente de Google se encargará de renovar el token de acceso cuando caduque (el token de renovación se encuentra presumiblemente en el archivo XML de secretos), pero no muestra cómo detectaría que el token de acceso ha cambiado para que pueda ser guardado en la aplicación para el próximo acceso. ¿Hay una devolución de llamada para esto, o una aplicación siempre debe verificar si el token de acceso ha cambiado en cada acceso remoto que realiza?
Jason
10

Este es un código completo en PHP usando el SDK oficial de Google

$client = new Google_Client();
## some need parameter
$client->setApplicationName('your application name');
$client->setClientId('****************');
$client->setClientSecret('************');
$client->setRedirectUri('http://your.website.tld/complete/url2redirect');
$client->setScopes('https://www.googleapis.com/auth/userinfo.email');
## these two lines is important to get refresh token from google api
$client->setAccessType('offline');
$client->setApprovalPrompt('force'); # this line is important when you revoke permission from your app, it will prompt google approval dialogue box forcefully to user to grant offline access
Shahadat Hossain Khan
fuente
8

Para nuestra aplicación, tuvimos que usar ambos parámetros access_type=offline&prompt=consent. approval_prompt=force no funcionó para nosotros

Ricky
fuente
1
Gracias Ricky, esto es lo que también me funcionó. Creo que las respuestas anteriores, sugiriendo approval_prompt=force, probablemente eran correctas en ese momento, pero ya no funcionan. Hay algo de discusión aquí: github.com/google/oauth2client/issues/453
Mike Morearty
7

Hola, seguí los siguientes pasos y pude obtener el token de actualización.

El flujo de autorización tiene dos pasos.

  1. Consiste en obtener el código de autorización mediante https://accounts.google.com/o/oauth2/auth?URL.

    Para eso, se envía una solicitud de publicación que proporciona los siguientes parámetros. 'scope=' + SCOPE + '&client_id=' + CLIENTID + '&redirect_uri=' + REDIRECT + '&response_type=' + TYPE + '&access_type=offline'Proporcionar lo anterior recibirá un código de autorización.

  2. Recuperando AcessToken y RefreshToken usando https://accounts.google.com/o/oauth2/token?URL. Para eso, se envía una solicitud de publicación que proporciona los siguientes parámetros.

    "código": código, "client_id": CID, "client_secret": CSECRET, "redirect_uri": REDIRECT, "grant_type": "código_autorización",

Entonces, en su primer intento, una vez que autorice los permisos, podrá obtener el token de actualización. Los intentos posteriores no proporcionarán el token de actualización. Si desea el token nuevamente, revoque el acceso en su aplicación.

Espero que esto ayude a alguien a aplaudir :)

dnWick
fuente
4

OAuth tiene dos escenarios en modo real. El estilo de acceso normal y predeterminado se llama en línea. En algunos casos, su aplicación puede necesitar acceder a una API de Google cuando el usuario no está presente, es escenarios fuera de línea. Se obtiene un token de actualización en escenarios fuera de línea durante el primer intercambio de código de autorización.

Para que pueda obtener referh_token en algunos escenarios, no en todos.

puede tener el contenido en https://developers.google.com/identity/protocols/OAuth2WebServer#offline .

Julian89757
fuente
0

Para aquellos que usan la biblioteca cliente de la API de Google para PHP y buscan acceso sin conexión y tokens de actualización, tengan cuidado al momento de escribir este artículo, los documentos muestran ejemplos incorrectos.

actualmente está mostrando:

$client = new Google_Client();
$client->setAuthConfig('client_secret.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
// offline access will give you both an access and refresh token so that
// your app can refresh the access token without user interaction.
$client->setAccessType('offline');
// Using "consent" ensures that your application always receives a refresh token.
// If you are not using offline access, you can omit this.
$client->setApprovalPrompt("consent");
$client->setIncludeGrantedScopes(true);   // incremental auth

fuente: https://developers.google.com/identity/protocols/OAuth2WebServer#offline

Todo esto funciona muy bien, excepto UNA pieza

$client->setApprovalPrompt("consent");

Después de un poco de razonamiento, cambié esta línea a la siguiente y TODO FUNCIONÓ

$client->setPrompt("consent");

Tiene sentido, ya que al usar las solicitudes HTTP, se cambió de Approved_prompt = force a prompt = consent . Entonces, cambiar el método de establecimiento de setApprovalPrompt a setPrompt sigue la convención natural, ¡PERO NO ESTÁ EN LOS DOCUMENTOS! Eso lo encontré al menos.

Arrendajo
fuente