Получение одноразового кода авторизации Google

У меня возникли проблемы с получением одноразового кода авторизации от Google. Я пытаюсь получить код авторизации от клиента Android, чтобы я мог отправить его в мой Rails-сервер (веб-клиент).

В моей консоли Google Cloud Developer у меня есть приложение с двумя идентификаторами клиента:

  1. Идентификатор клиента для веб-приложения (для моего бэкэнд-рельсов)

  2. Идентификатор клиента для Android-приложения (для моего клиента android). SHA1 используется от ~ / .android / debug.keystore

Предположим, что идентификатор клиента веб-приложения: 12345.apps.googleusercontent.com

Предположим, что идентификатор клиента Android – 67890.apps.googleusercontent.com

Это мой код:

 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); } 

Некоторые дополнительные примечания

  • Я нахожусь в исключении GoogleAuthException и получаю «Неизвестно» как деталь сообщения

  • Я не могу добавить дополнительных членов в разрешения Облачной консоли Google для этого проекта – при добавлении нового члена появляется всплывающее окно с «Ошибка сервера. Упс! Наш плохой». Я дважды отправлял обратную связь в Google.

  • Я имею в виду эту документацию . Обратите внимание на приведенную ниже цитату. «Исправлено», говорят ли они, что мне не нужно добавлять аудиторию: server: client_id в моей переменной GOOGLE_CALENDAR_API_SCOPE? Я пробовал как с, так и без него и все еще получаю то же исключение GoogleAuthException.

В этой ситуации приложение Android может вызывать метод GoogleAuthUtil.getToken () от имени любой из учетных записей Google на устройстве и значение аргумента области аудитории: server: client_id: 9414861317621.apps.googleusercontent.com. Префиксная аудитория: server: client_id: исправлена, а остальная строка области видимости – это идентификатор клиента веб-компонента.

  • Если я использую эту область действия, я могу аутентифицироваться с помощью Google с устройства. Тем не менее, документация, которую я прочитал, предполагает, что мне нужно использовать идентификатор веб-клиента сервера (который находится в том же проекте консоли Google как идентификатор клиента android) в области, чтобы сервер мог попасть в google api от имени Пользователь, который разрешил его клиенту android:

    private final static String GOOGLE_CALENDAR_API_SCOPE = "oauth2:https://www.googleapis.com/auth/calendar";

ОБНОВЛЕНИЕ 1

Я изначально добавил в ответ: причина моей первой проблемы – я попал в исключение GoogleAuthException и получаю сообщение «Неизвестно» в качестве детали сообщения – была ошибка, которую я допустил при добавлении идентификатора клиента Android в облачную консоль. SHA1 был правильным, но я не набрал имя пакета правильно. Я использовал com.company.app, когда мой пакет android на самом деле com.company.android.app. Код в исходном вопросе отлично работает. Просто убедитесь, что у вас есть все необходимые клиенты в проекте Google Cloud Console.

Но еще одна проблема все еще существует. Когда я отправляю одноразовый токен авторизации, возвращенный из GoogleAuthUtil.getToken () в бэкэнд Rails, а затем попытаюсь обменять его на access_token и refresh_token, я получаю следующее:

 Signet::AuthorizationError: Authorization failed. Server message: { "error" : "invalid_grant" } 

Эта документация google и несколько сообщений SO указывают, что мне нужно установить access_type=offline . Но я думаю, что это когда вы запрашиваете одноразовый код авторизации и автономный доступ с веб-сервера. Я пытаюсь запросить одноразовый код авторизации от клиента Android и отправить его на веб-сервер.

Возможно ли это с помощью GoogleAuthUtil.getToken () ?

ОБНОВЛЕНИЕ 2

Вход Google Plus должен находиться в области, даже если вы только пытаетесь получить доступ к календарю:

 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"; 

Это сообщение было полезно. Кроме того, в документации по идентификатору кросс-клиента Google указано :

[Примечание: эта политика постепенно развертывается. На данный момент, когда применяются токены доступа, он применяется только тогда, когда запрашиваемые области включают https://www.googleapis.com/auth/plus.login.]

Я подведу итог в ответе, если обмен токена работает на бэкэнде Rails.

Для меня это решили две вещи:

  1. Убедитесь, что идентификаторы Android и веб-клиента настроены правильно в том же проекте Google Cloud Console.

  2. Используйте правильную область. Плюс вход необходим, даже если вы только получаете доступ к календарю api:

    // идентификатор веб-сервера, который обменивает код аутентификации для доступа и обновления токенов

    Private final static String WEB_CLIENT_ID = "12345.apps.googleusercontent.com"; 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 " ;

Вот что я сделал:

 final String authToken = GoogleAuthUtil.getTokenWithNotification (this.context, account.name, "oauth2:" + AuthUtils.profileScope, new Bundle (), Contract.authority, new Bundle ()); 

Но вы просто getToken должны работать одинаково для работы на переднем плане.

Возьмите этот токен, отправьте его на сервер таким образом, что вы можете использовать его как HTTP-заголовок (через HTTPS). Пока область сервера является подмножеством области, используемой для получения токена, у вас не должно быть проблем. Сервер использует идентификатор сервера, а клиент android использует идентификатор клиента android.

Вы должны установить свою область действия:

 oauth2:https://www.googleapis.com/auth/calendar 

или

 oauth2:https://www.googleapis.com/auth/calendar.readonly 

См. https://developers.google.com/google-apps/calendar/auth

Изменить: ОК. Я вижу, что вы пытаетесь сделать. Значение области – это список, разделенный пробелами, поэтому вам, вероятно, потребуется добавить аудиторию: server: client_id: к вашей области, например:

 "oauth2:https://www.googleapis.com/auth/calendar audience:server:client_id:12345-your-web-component-client-id"