Cómo obtener el código de autorización de Google una sola vez
Tengo problemas para obtener un código de autorización único de Google. Estoy intentando obtener el código de autorización de un cliente de Android para poder enviarlo a mi backend de Rails (cliente web).
En mi consola de Google Cloud Developer, tengo una aplicación con dos ID de cliente:
- Sincronizar cliente Android y servidor REST
- Solución de empuje de servidor en Rails
- La mejor práctica al permitir que sólo la aplicación de Android acceda a Rails API
- ¿Cómo crear un Api seguro de Rails REST para mi aplicación?
- Notificaciones Push utilizando el servidor Rails
-
ID de cliente para la aplicación web (para mi backend de rieles)
-
ID de cliente para la aplicación de Android (para mi cliente android). El SHA1 utilizado es de ~ / .android / debug.keystore
Supongamos que el ID de cliente de aplicaciones web es 12345.apps.googleusercontent.com
Supongamos que el ID del cliente Android es 67890.apps.googleusercontent.com
Este es parte de mi código:
private final static String WEB_CLIENT_ID = "12345.apps.googleusercontent.com"; private final static String GOOGLE_CALENDAR_API_SCOPE = "audience:server:client_id:" + WEB_CLIENT_ID; private void getAndUseAuthToken(final String email) { AsyncTask task = new AsyncTask<String, Void, String>() { @Override protected String doInBackground(String... emails) { try { return GoogleAuthUtil.getToken(AddExternalCalendarsActivity.this, emails[0], GOOGLE_CALENDAR_API_SCOPE); } catch (UserRecoverableAuthException e) { startActivityForResult(e.getIntent(), IntentConstants.REQUEST_GOOGLE_AUTHORIZATION); } catch (IOException e) { e.printStackTrace(); } catch (GoogleAuthException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(String authToken) { if (authToken != null) { saveTokenAndGetCalendars(email, authToken); } } }; String[] emails = new String[1]; emails[0] = email; task.execute(emails); }
Algunas notas adicionales
-
Estoy golpeando la excepción de GoogleAuth y recibir "Desconocido" como el detalle del mensaje
-
No puedo agregar miembros adicionales a los permisos de Google Cloud Console para este proyecto: al agregar un nuevo miembro, aparece un mensaje emergente con "Error de servidor. He enviado comentarios a Google dos veces.
-
Me refiero a esta documentación . Observe la siguiente cita. Por "fijo", ¿están diciendo que no necesito prepagar audiencia: server: client_id en mi GOOGLE_CALENDAR_API_SCOPE variable? He intentado tanto con y sin y todavía obtener la misma excepción GoogleAuthException.
En esta situación, la aplicación de Android puede llamar al método GoogleAuthUtil.getToken () en nombre de cualquiera de las cuentas de Google del dispositivo y con un valor de argumento de ámbito de audiencia: server: client_id: 9414861317621.apps.googleusercontent.com. El prefijo público: server: client_id: es fijo, y el resto de la cadena del ámbito es el ID del cliente del componente web.
-
Si utilizo este ámbito, puedo autenticarme con google desde el dispositivo. Sin embargo, la documentación que he leído sugiere que necesito utilizar el ID de cliente web de servidor (que está en el mismo proyecto de consola de Google que el ID de cliente de android) en el ámbito para que el servidor toque la API de google en nombre de El usuario que lo autorizó en el cliente android:
private final static String GOOGLE_CALENDAR_API_SCOPE = "oauth2:https://www.googleapis.com/auth/calendar";
ACTUALIZACIÓN 1
Originalmente añadí en respuesta: La razón de mi primer problema – Estoy golpeando la excepción GoogleAuthException y recibir "Desconocido" como el detalle del mensaje – fue un error que hice al agregar la identificación del cliente android en la consola de la nube. El SHA1 era correcto pero no escribí correctamente el nombre del paquete. He utilizado com.company.app cuando mi paquete android es en realidad com.company.android.app. El código en la pregunta original funciona bien. Sólo asegúrate de tener todos los clientes necesarios en tu proyecto de Google Cloud Console.
Pero todavía existe otro problema. Cuando envío el token de autorización de una sola vez devuelto de GoogleAuthUtil.getToken () al backend de Rails, y luego intento cambiarlo por un access_token y refresh_token, obtengo el siguiente:
Signet::AuthorizationError: Authorization failed. Server message: { "error" : "invalid_grant" }
Esta documentación de google y varias publicaciones de SO sugieren que necesito establecer access_type=offline
. Pero creo que es cuando se solicita el código de autorización de una sola vez y el acceso sin conexión desde un servidor Web. Estoy intentando solicitar el código de autorización única de un cliente de Android y enviarlo al servidor web.
¿Es esto posible con GoogleAuthUtil.getToken () ?
ACTUALIZAR 2
El inicio de sesión de Google Plus debe estar en el ámbito aunque solo intentes acceder al calendario:
private final static String GOOGLE_CALENDAR_API_SCOPE = "oauth2:server:client_id:" + WEB_CLIENT_ID + ":api_scope:https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/calendar";
Este post de SO fue útil. Además, la documentación de identidad de Cross Client de Google indica:
[Nota: Esta política se está desarrollando gradualmente. Por el momento, cuando los tokens de acceso están involucrados, sólo se aplica cuando los ámbitos solicitados incluyen https://www.googleapis.com/auth/plus.login.]
Resumiré en una respuesta si el intercambio simbólico funciona en el backend de Rails.
- Solicitud POST con Retrofit dando 500
- Cómo Firebase Auth con Rails?
- Grape Rails API con Android
- Subida de imagen de Base64 VS ¿Subida de imagen binaria?
- Publicar en Ruby on Rails la aplicación de android
- Creación de aplicaciones para iphone y Android para aplicaciones de rails existentes
- ActionController InvalidAuthenticityToken en Api :: V1 :: UsersController # create
- Autenticación mediante Facebook a través de Rails API
Dos cosas resolvieron esto para mí:
-
Asegúrese de que los ID de cliente de Android y Web se configuran correctamente en el mismo proyecto de Google Cloud Console.
-
Utilice el alcance correcto. El inicio de sesión adicional es necesario incluso si solo accedes al api del calendario:
// el id del servidor web que está intercambiando el código de autenticación para los tokens de acceso y actualización
Private final static String WEB_CLIENT_ID = "12345.apps.googleusercontent.com"; Private final static String GOOGLE_CALENDAR_API_SCOPE = "oauth2: servidor: id_cliente:" + WEB_CLIENT_ID + ": api_scope: https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/calendar " ;
Esto es lo que he hecho:
final String authToken = GoogleAuthUtil.getTokenWithNotification (this.context, account.name, "oauth2:" + AuthUtils.profileScope, new Bundle (), Contract.authority, new Bundle ());
Pero usted getToken llano debe trabajar iguales para una actividad del primero plano.
Tome este símbolo, enviarlo al servidor de una manera que puede utilizar como un encabezado HTTP (a través de HTTPS). Siempre y cuando el ámbito del servidor sea un subconjunto del ámbito utilizado para adquirir el token, no debería tener ningún problema. El servidor utiliza la identificación del servidor y el cliente android utiliza la identificación del cliente android.
Deberá establecer su alcance en:
oauth2:https://www.googleapis.com/auth/calendar
o
oauth2:https://www.googleapis.com/auth/calendar.readonly
Consulta la página https://developers.google.com/google-apps/calendar/auth.
Edit: OK Veo lo que estás tratando de hacer. El valor del ámbito es una lista separada por espacios, por lo que es probable que tenga que añadir audiencia: server: client_id: a su ámbito de aplicación como:
"oauth2:https://www.googleapis.com/auth/calendar audience:server:client_id:12345-your-web-component-client-id"
- ¿Cómo calcula Android el caché y el tamaño de los datos?
- Tema no aplicado con la biblioteca appcompat en algunos dispositivos Android 4.X