studio setaccesstype secret library google for apis oauth-2.0 google-calendar-api google-oauth google-api-java-client

setaccesstype - Mensaje "No requerido para iniciar sesión" 401 no autorizado al llamar a la API v3 de Google Calendar usando una cuenta de servicio a través de OAuth 2.0



refresh token google api (6)

Primero, permítame explicarle lo que estoy tratando de hacer, ya que esta es una pregunta de dos partes.

Estoy creando un servicio JAX-RS que se autentica internamente con una cuenta de Google a través de OAuth2, para que pueda acceder y manipular un calendario de Google. Este servicio lo llamará un sitio web (Joomla), que permitirá a los usuarios que inicien sesión en el sitio registrar su dirección de correo electrónico con eventos del calendario para que puedan recibir notificaciones por correo electrónico cuando estén cerca. Estos usuarios no tienen conocimiento de la cuenta de Google subyacente.

Entonces, mi primera pregunta, ¿es la autenticación de la cuenta de servicio lo correcto? En cuanto a los documentos de Google, es el único caso de uso que satisface la autenticación no humana (por lo tanto, la autenticación de servidor a servidor).

El segundo problema es que escribí algo de código para hacer esto, pero recibo una respuesta 401 / No autorizada que devuelve el siguiente error cuando llamo al método de ejecución el feed del calendario. Este código fue sacado de las muestras de Google.

Estoy usando v3-rev3-1.5.0-beta de la API de Google Calendar. He activado la API del calendario en la cuenta y he creado y descargado una clave privada, que se utiliza en el código a continuación.

Estoy llamando al código de abajo en Eclipse localmente, no desde un servidor web.

Así que la primera llamada que hago es recuperar un objeto de credencial (la identificación está oculta con las X):

private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); private static final JsonFactory JSON_FACTORY = new JacksonFactory(); . . . GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT) .setJsonFactory(JSON_FACTORY) .setServiceAccountId("[email protected]") .setServiceAccountScopes(CalendarScopes.CALENDAR) .setServiceAccountPrivateKeyFromP12File(new File("D:/3cd8XXXXXXXXXXXXXXXXXXXXXXXXXXXXXd635e-privatekey.p12")) .build();

El siguiente paso es llamar a la API del calendario, así (no hay otro código entre ellos):

Calendar calendar = Calendar.builder(HTTP_TRANSPORT, JSON_FACTORY) .setApplicationName("TestApp-Calendar/1.0").setHttpRequestInitializer(credential) .build(); CalendarList feed = calendar.calendarList().list().execute();

La llamada a list (). Execute () produce el siguiente error:

com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 No autorizado {"code": 401, "errors": [{"domain": "global", "location": "Authorization", "locationType": " header "," message ":" Login Required "," reason ":" required "}]," message ":" Login Required "} at com.google.api.client.googleapis.json.GoogleJsonResponseException.from (GoogleJsonResponseException. java: 159) en com.google.api.client.googleapis.json.GoogleJsonResponseException.execute (GoogleJsonResponseException.java:187) en com.google.api.client.googleapis.services.GoogleClient.executeUnpac en com.google.api.client.http.json.JsonHttpRequest.executeUnparsed (JsonHttpRequest.java:112) en com.google.api.services.calendar.Calendar $ CalendarList $ List.execute (Calendar.java:510) en el uk .org.reigatepriorybowmen.Service.registerEmailForAllCalendarEvents (Service.java:55) en uk.org.reigatepriorybowmen.Service.main (Service.java:74)

La cuenta de servicio se configura de la siguiente manera:

Entonces, ¿qué estoy haciendo mal? He pasado horas buscando en Google buscando soluciones, así que esta es mi última esperanza.

Muchas gracias de antemano por su ayuda.

Justin


¿Solicitó permiso para los ámbitos adecuados? Siempre debe incluir https://www.googleapis.com/auth/userinfo.profile


Bien, he estado jugando con esto y he superado el error 401, pero ahora estoy alcanzando un 403. Sin embargo, detallaré el código que he escrito que al menos responde al problema 401.

No modifiqué ninguna de las configuraciones de la cuenta de servicio ni volví a generar ninguna de las claves, etc., es lo mismo.

Lo que ha cambiado es parte del código, y actualicé a v3r20lv1.12.0-beta de la API del calendario.

El código a continuación, como se detalla arriba en el OP, sigue siendo el mismo, es decir:

private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); private static final JsonFactory JSON_FACTORY = new JacksonFactory(); . . . GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT) .setJsonFactory(JSON_FACTORY) .setServiceAccountId("[email protected]") .setServiceAccountScopes(CalendarScopes.CALENDAR) .setServiceAccountPrivateKeyFromP12File(new File("D:/3cd8XXXXXXXXXXXXXXXXXXXXXXXXXXXXXd635e-privatekey.p12")) .build();

El código para obtener un identificador para el calendario ha cambiado, pero esto fue forzado por un cambio de API:

Calendar calendar = new Calendar(HTTP_TRANSPORT, JSON_FACTORY, credential);

En este punto, puedo recorrer mi calendario y ver los eventos ejecutando el siguiente código (esto imprime un resumen de eventos):

Events events = calendar.events().list(CALENDAR_ID).execute(); for (Event event : events.getItems()) { System.out.println(event.getSummary()); }

Pero, si intento actualizar un evento, obtengo un error 403 Prohibido. Levantaré un hilo separado para esto, y enlazaré los dos hilos juntos.

¡Gracias a todos por vuestra ayuda!

EDIT: here está el nuevo hilo.


Creo que deberás especificar el usuario que estás intentando suplantar.

La forma en que está utilizando ServiceAccount en este momento solo es válida para acceder a los datos relacionados con su aplicación o con su cuenta de servicio. Como desea acceder a los datos de Google Calendar, debe ser un administrador de dominio de Google Apps con privilegios para acceder a los datos de los usuarios de su dominio; avíseme si no estoy en lo correcto. Los datos de Google Calendar pertenecen a los usuarios, por lo que debe especificar a qué usuario está intentando hacerse pasar.

Para hacer esto usando Java, parece que necesitas usar GoogleCredential.Builder#setServiceAccountUser(String)

Por favor, inténtalo:

GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT) .setJsonFactory(JSON_FACTORY) .setServiceAccountId("[email protected]") .setServiceAccountScopes(CalendarScopes.CALENDAR) .setServiceAccountPrivateKeyFromP12File(new File("/path/to/privatekey.p12")) .setServiceAccountUser("[email protected]") .build();

Además, una vez que haya creado una clave de Cuenta de servicio en su proyecto de API (desde la Consola de API), deberá agregar este proyecto a la lista de aplicaciones de terceros autorizados en cPanel. Más información sobre esto se puede encontrar here . La "Identificación del cliente" que debe usar es la que está vinculada a la clave de la Cuenta de servicio y se parece a <APP_ID>-<OTHER_KEY>.apps.googleusercontent.com


Dicho comportamiento puede ocurrir si no agregó un usuario de api en el panel de administración (en su caso, el panel de Documentos supongo), por ejemplo, en Google Analytics tiene que agregar un nuevo usuario donde la dirección de correo electrónico es la misma que la que recibió de api (proporcionada por el Cuenta de servicio API de Google, después de crear la clave privada). En analítica se ve así:


En cuanto al 401, parece una rareza con la API de Google. Encuentro la primera vez que ejecuto mi aplicación en un tiempo, y luego, a intervalos aparentemente aleatorios, con las horas separadas, siempre obtengo un 401. En la segunda o tercera ronda, realmente se registra.

El comportamiento se explica incluso en el código de muestra de la API de tareas de Google here .

Note este código:

void onRequestCompleted() { received401 = false; } void handleGoogleException(IOException e) { if (e instanceof GoogleJsonResponseException) { GoogleJsonResponseException exception = (GoogleJsonResponseException) e; if (exception.getStatusCode() == 401 && !received401) { received401 = true; accountManager.invalidateAuthToken(credential.getAccessToken()); credential.setAccessToken(null); SharedPreferences.Editor editor2 = settings.edit(); editor2.remove(PREF_AUTH_TOKEN); editor2.commit(); gotAccount(); return; } } Log.e(TAG, e.getMessage(), e);

}

En el ejemplo de código propio de Google, han previsto por primera vez el 401. Es posible que sea un problema de seguridad especial que deba manejarse en el código.


Soy un desarrollador de aplicaciones móviles Android. Estoy haciendo una aplicación utilizando la API de Google Calendar (OAuth 2.0). También me enfrenté a este mismo error. Pero ahora, he resuelto el error. Estoy escribiendo el escenario y la solución para ello.
La url de obtener el Evento de calendario para el calendario en particular (API de aplicación móvil):

https://www.googleapis.com/calendar/v3/calendars/en.indian%23holiday%40group.v.calendar.google.com/events?access_token=ya29.AHES6ZQyP3iDZM8PF-7ZqZE8oKmWAgUX55sPGPTjGbM5A

En este url, tenemos que agregar el ID de calendario. El formato de la url es;

https://www.googleapis.com/calendar/v3/calendars/<calendarId>/events

No estaba codificando el ID de calendario antes de agregarlo a la URL. Codifiqué el ID de calendario y luego realicé la solicitud Http. Todo fue bien entonces.

final String accessToken=dataStore.getAccessToken(); List<NameValuePair> params = new LinkedList<NameValuePair>(); params.add(new BasicNameValuePair("access_token", accessToken)); String paramString = URLEncodedUtils.format(params, "utf-8"); final String url = String.format(AuthConstants.CALENDAR_EVENTS_URI,URLEncoder.encode(calendarId))+"?"+ paramString;

Ahora los eventos del calendario se devuelven en el JSON.