Как работает google-api в автономном запросе с токенами - PullRequest
2 голосов
/ 04 апреля 2019

Моя первая проблема заключается в том, что когда я делаю экземпляр Google_Client и устанавливаю все необходимые scopes, configs, access types и others, а затем генерирую URL-адрес для пользователя AUTH с $client->createAuthUrl(); Я разрешаю доступ к своему приложению с помощью учетной записи Google, в которую я вошел.Все работает нормально, пока мне не нужно обновить токен.

Я объясняю ниже об обновлении токена.

  $this->client = new Google_Client();
            $this->client->setAuthConfig(Storage::path('secret.json'));
            $this->client->setAccessType("offline");        // offline access
            $this->client->setIncludeGrantedScopes(true);   // incremental auth
            $this->client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
            $this->client->setRedirectUri(env('APP_URL') . '/login/google/callback');

Итак, следующее, что я сделал, это получил данные пользователя Google с помощью laravel-socialite. Это данныеЯ получаю:

Код для запроса

  public function redirectToGoogleProvider()
    {
        $parameters = ['access_type' => 'offline'];

        return Socialite::driver('google')
            ->scopes(["https://www.googleapis.com/auth/drive"])
            ->with($parameters)
            ->redirect();
    }
User {#466 ▼
  +token: "ya29.GmPhBiSuYJ_oKsvDTUXrj3lJR5jlEYV4x8d0ZuYZLnDJgYL-uePT_KuUkIb-OQUiWBElhm6ljfac5QhDTXYK3qjWjje1vsnZsTAJ7pXyjNAVd2buZy0a6xZCTdnLdFNMKMDMXa6bGbA"
  +refreshToken: null
  +expiresIn: 3599
  +id: "101509757451285102354"
  +nickname: null
  +name: "My name"
  +email: "My email"
  +avatar: "https://lh3.googleusercontent.com/-Qsbr3VmcZ50/AAAAAAAAAAI/AAAAAAAAAAA/ACHi3rdS2HIl3LCv5EYCmvyXulG8n-Ap7w/mo/photo.jpg"
  +user: array:12 [▶]
  +"avatar_original": "https://lh3.googleusercontent.com/-Qsbr3VmcZ50/AAAAAAAAAAI/AAAAAAAAAAA/ACHi3rdS2HIl3LCv5EYCmvyXulG8n-Ap7w/mo/photo.jpg"
}

Здесь нет токена обновления.Я предполагаю, что это связано с тем, что Google работает в автономном режиме

После того, как пользователь предоставил автономный доступ к запрошенным областям, вы можете продолжать использовать клиент API длядоступ к API Google от имени пользователя, когда пользователь находится в автономном режиме.Клиентский объект будет обновлять токен доступа по мере необходимости.

Поэтому я установил токен, полученный из запроса и сохраняющий в базе данных, к экземпляру Google_Client с

$client->setAccessToken(Auth::user()->getUserInfo()->refresh_token)

Это работает.Но когда токен нужно обновить, он не обновляется.Вместо этого я получаю

"Недопустимая ошибка creditianals".

Google говорит, что:

"Клиентский объект обновит доступжетон по мере необходимости. "Но этого не происходит.

Я не понимаю, нужно ли мне вызывать специальный метод или как Google_Client обрабатывает обновление токена.

Я пыталсяиспользуйте CODE parameter для получения токена и обновления токена вместе с ним.

$client->fetchAccessTokenWithAuthCode($code);

И получил эту ошибку:

array:2 [▼
  "error" => "invalid_request"
  "error_description" => "Could not determine client ID from request."
]

Возможно, я что-то не так делаю, но понятия не имею, что.Я смущен, если честно.Уже потерял день без успеха.

Ответы [ 2 ]

1 голос
/ 04 апреля 2019

Вы получите токен обновления только при первом запросе доступа пользователя.После этого Google предполагает, что вы сохранили токен обновления.

Попросите пользователя зайти в свою учетную запись Google и отозвать доступ, предоставленный этому клиентскому приложению.

Перейдите на страницу, показывающую приложения с доступом к вашей учетной записи:

  • https://myaccount.google.com/u/0/permissions.
  • В меню сторонних приложений выберите приложение.
  • Нажмите «Удалить доступ», затем нажмите «ОК» для подтверждения

Затем попросите их снова подтвердить подлинность вашего приложения.Вы должны увидеть обновленный ток в то время.Обязательно сохраните его.

revoke

Вы также можете сделать

$client->revokeToken();

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

refresh access

Это мой код для обновления токена доступа.выглядит очень близко, вы должны быть в состоянии скрыть это, если это не работает из коробки

/**
 * Authenticating to Google using Oauth2
 * Documentation:  https://developers.google.com/identity/protocols/OAuth2
 * Returns a Google client with refresh token and access tokens set. 
 *  If not authencated then we will redirect to request authencation.
 * @return A google client object.
 */
function getOauth2Client() {
    try {

        $client = buildClient();

        // Set the refresh token on the client. 
        if (isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) {
            $client->refreshToken($_SESSION['refresh_token']);
        }

        // If the user has already authorized this app then get an access token
        // else redirect to ask the user to authorize access to Google Analytics.
        if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {

            // Set the access token on the client.
            $client->setAccessToken($_SESSION['access_token']);                 

            // Refresh the access token if it's expired.
            if ($client->isAccessTokenExpired()) {              
                $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
                $client->setAccessToken($client->getAccessToken()); 
                $_SESSION['access_token'] = $client->getAccessToken();              
            }           
            return $client; 
        } else {
            // We do not have access request access.
            header('Location: ' . filter_var( $client->getRedirectUri(), FILTER_SANITIZE_URL));
        }
    } catch (Exception $e) {
        print "An error occurred: " . $e->getMessage();
    }
}
0 голосов
/ 15 июня 2019

Позвольте мне поделиться тем, что я наконец-то придумал в Laravel, чтобы заставить его работать

public static function getOauth2Client($o_user, $f_client) {
    try {
        $o_client = new Google_Client();
        $o_client - >setAuthConfig($f_client);
        $o_client - >setAccessType('offline');
        $o_client - >setIncludeGrantedScopes(true);
        $i_token_remaining = ($o_user - >gdrive_access_ttl - (time() - $o_user - >gdrive_access_created));
        $google_client_token = ['refresh_token' = >$o_user - >gdrive_refresh_token, 'access_token' = >$o_user - >gdrive_access_token, 'created' = >$o_user - >gdrive_access_created, 'expires_in' = >$i_token_remaining, ];
        $o_client - >setAccessToken(json_encode($google_client_token));

        #token validity time is less than 60 seconds
        if ($i_token_remaining < 60 || $o_client - >isAccessTokenExpired()) {
            $res = $o_client - >fetchAccessTokenWithRefreshToken($o_client - >getRefreshToken());
            $o_user - >gdrive_access_token = $res['access_token'];
            $o_user - >gdrive_access_created = time();
            $o_user - >gdrive_access_ttl = $res['expires_in'];
        }
        return $o_client;
    } catch(Exception $e) {
        print 'An error occurred: '.$e - >getMessage();
    }
}

По моему опыту:

  • setAccessToken не будет работать только с токеном, он требует от меня «expires_in»
  • $ o_client-> isAccessTokenExpired () всегда возвращает значение true, если «создан» не предоставлен с $ google_client_token, поскольку «создан» учитывается для истечения срока действия
  • isAccessTokenExpired проверяет 30 секунд до истечения срока действия, поэтому моя 60-секундная проверка может быть безопасно удалена
  • $ o_user - объект пользователя, например Пользователь :: найти ($ i_user_id);
  • токен обновления никогда не меняется, он устанавливается один раз и навсегда, только маркер доступа изменяется при запросе обновления
  • токен доступа ttl равен 3600 - угадайте, почему?)) - поэтому, пожалуйста, также сохраните и обновите токен доступа
  • из области действия этой функции я также обновляю свою БД после изменения токена доступа
User::updateOrCreate(
    ['email' => $o_user - > email],
    [
        'gdrive_access_token' => $o_user - > gdrive_access_token,
        'gdrive_access_created' => $o_user - > gdrive_access_created,
        'gdrive_access_ttl' => $o_user - > gdrive_access_ttl,
    ]);
...