unauthorized_client ошибка при использовании клиента PHP для refreshToken с клиентом Google API?

Я запрашиваю доступ к данным пользователя из приложения IOS, используя этот код из модуля GoogleSignIn.

 [GIDSignIn sharedInstance].uiDelegate = self;
 [[GIDSignIn sharedInstance] setScopes:@[ ... ];
 [[GIDSignIn sharedInstance] signInSilently];

Затем я получаю accessToken и refreshToken в appDelegate и отправляю их на сервер, на котором запущен PHP и использует эту клиентскую библиотеку Google (https://github.com/googleapis/google-api-php-client) ... в течение первого часа все работает нормально, и токен доступа действителен и разрешает мне доступ во все области. Затем через час токен доступа истекает, и я пытаюсь обновить его с помощью этого кода.

$client = new Google_Client();
$client->setApplicationName(<app name>);
$client->setDeveloperKey(<google_oauth_developer_key>);
$client->setClientSecret(<google_oauth_client_secret>);
$client->setClientId(<google_oauth_client_id>);
$client->refreshToken("1/12ju3ZZim-r6co195lIVNNvzBq9x5G64GJCWkYsOQ18");

и приведенная выше функция "refreshToken" возвращает эту ошибку.

=> [
     "error" => "unauthorized_client",
     "error_description" => "Unauthorized",
   ]

Стоит отметить, что app name, google_oauth_developer_key, google_oauth_client_secret и google_oauth_client_id не изменились. Это те же самые, которые раньше работали для получения контактов пользователя, событий календаря и т. Д., Когда токен доступа еще не истек.

Что могло быть причиной этой ошибки?


person Yaseen Aniss    schedule 15.01.2019    source источник


Ответы (2)


В какой-то момент вам действительно нужно использовать токен обновления.

if ($client->isAccessTokenExpired()) {
        $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
        $client->getAccessToken();

Код скопирован из моего Пример Oauth2Authentication.php

Примечание

Также помните, что токены обновления основаны на пользователе / ​​клиенте. Таким образом, если токен был сгенерирован одним клиентом, другой клиент, вероятно, не сможет его использовать. Я буду очень удивлен, если вы сможете использовать токен обновления, созданный в коде iOS, в приложении php. Типы клиентов разные.

person DaImTo    schedule 15.01.2019
comment
Спасибо за ответ. Я думаю, что отдельные клиенты ДЕЙСТВИТЕЛЬНО работают, потому что они позволяют мне получить доступ ко всем областям, и все работает нормально до тех пор, пока не истечет токен доступа ... Приложение все то же самое, только разные идентификаторы клиентов - person Yaseen Aniss; 15.01.2019
comment
Итак, использование токена доступа без идентификатора клиента и обновление токена доступа с использованием другого идентификатора клиента - это разные вещи. Попробуйте код и посмотрите, что произойдет. - person DaImTo; 15.01.2019
comment
Я попробовал код, и он не прошел с ошибкой PHP Notice: Undefined index: expires_in in /app/vendor/google/apiclient/src/Google/Client.php on line 484 ... когда я позвонил _2 _... Не могли бы вы показать мне, как выглядит токен доступа? Моя выглядит так - ›ya29.GluSBn-ektRuma45i1ILoKXGYWkSDv5XgAY84px2OZ0-5X2Efjsja2Ij4ne-Zun75w5rw3NVok9-Sj9G3sdW1n4jD7mH9_4h4CT_Rm5xqtNuDjeWB0jSqUZss-Pf, но я думаю, что это должен быть объект json, чтобы успешно вызывать эти другие функции (например, функция isAccessTokenExpired) - person Yaseen Aniss; 16.01.2019
comment
Вероятно, потому что он не может проверить токен доступа из IOS на основе другого идентификатора клиента. но он может это использовать. Предлагаю вам выбрать технологию. Однако из любопытства вы создали обоих клиентов в рамках одного проекта в консоли разработчика Google, верно? - person DaImTo; 16.01.2019
comment
Спасибо за помощь! я понял - person Yaseen Aniss; 16.01.2019

Итак, я понял, что сделал не так. Изначально я выполнил эти инструкции https://developers.google.com/identity/sign-in/ios/sign-in, которые предполагают, что вам нужен только онлайн-доступ, но мне действительно нужен автономный доступ к областям, поэтому я выполнил следующие инструкции https://developers.google.com/identity/sign-in/ios/offline-access, и теперь он работает. Поэтому вместо того, чтобы приложение IOS отправляло токен доступа и токен обновления отдельно, как это

- (void)signIn:(GIDSignIn *)signIn didSignInForUser:(GIDGoogleUser *)user
     withError:(NSError *)error {

    if (!error) {
        NSString *accessToken = user.authentication.accessToken;
        NSString *refreshToken = user.authentication.refreshToken;

Я просто прошу это послать serverAuthCode вот так

- (void)signIn:(GIDSignIn *)signIn didSignInForUser:(GIDGoogleUser *)user
     withError:(NSError *)error {

      if (!error) {
        NSString *serverAuthCode = user.serverAuthCode;

а затем на сервере я запускаю этот код, чтобы получить токен доступа

$access_token = $client->authenticate($google_server_auth_code);
$client->setAccessToken($access_token);

а затем, когда токен доступа истекает, я запускаю его, чтобы обновить его

$access_token = $client->refreshToken($client->getRefreshToken());
$client->setAccessToken($access_token);
person Yaseen Aniss    schedule 16.01.2019