Я следую за документами по ссылке ниже:
https://developers.google.com/+/mobile/android/sign-in#enable_server-side_api_access_for_your_app
В частности, часть, которая говорит:
Если вам не требуется автономный доступ, вы можете получить токен доступа и отправить его на свой сервер через защищенное соединение. Вы можете получить токен доступа напрямую, используя GoogleAuthUtil.getToken (), указав области без идентификатора клиента OAuth 2.0 вашего сервера. Например:
Я получаю токен доступа следующим образом:
accessToken = GoogleAuthUtil.getToken(
AuthenticatorActivity.this,
Plus.AccountApi.getAccountName(Common.mGoogleApiClient),
"oauth2:https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/plus.login email");
После того, как я получаю токен доступа, я отправляю его на веб-сервер, на веб-сервере я могу увидеть, что это действительный токен доступа, позвонив
https://www.googleapis.com/oauth2/v1/tokeninfo?access_token='.$_POST['google_access_token']
Приведенный выше запрос возвращает идентификатор клиента Android-приложений, а также корректно возвращает электронную почту пользователей.
Проблема в том, что когда я пытаюсь запустить $ client-> authenticate ($ _ POST [‘google_access_token’]); Я получаю исключение с сообщением: invalid_grant: неверный тип токена.
Чтобы предотвратить кэширование getToken, я всегда аннулирую токен в приложении для Android:
if (accessToken! = null && ! accessToken.isEmpty ()) {
GoogleAuthUtil.invalidateToken (AuthenticatorActivity.this, accessToken);
}
Вот код php:
if (!isset($_POST['google_access_token'])) {
throw new Exception('missing google_access_token');
}$client = new \Google_Client();
$client->setApplicationName("GiverHub");
$client->setClientId($this->config->item('google_client_id'));
$client->setClientSecret($this->config->item('google_client_secret'));
$client->setDeveloperKey($this->config->item('google_developer_key'));
$client->setRedirectUri($this->config->item('google_redirect_uri'));
$client->setScopes([
'https://www.googleapis.com/auth/plus.login',
'https://www.googleapis.com/auth/plus.me',
'email',
]);try {
$client->authenticate($_POST['google_access_token']); // if i remove this the rest of the code below works! ...
$reqUrl = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token='.$_POST['google_access_token'];
$req = new \Google_Http_Request($reqUrl);
$io = $client->getIo();
$response = $io->executeRequest($req);$response = $response[0];
$response = json_decode($response, true);
if ($response === null) {
throw new Exception('Failed to check token. response null');
}
if ($response['issued_to'] !== '466530377541-s7cfm34jpf818gbr0547pndpq9songkg.apps.googleusercontent.com') {
throw new Exception('Invalid access token. issued to wrong client id: '. print_r($response, true));
}
if (!isset($response['user_id'])) {
throw new Exception('Missing user_id');
}
if (!isset($response['email'])) {
throw new Exception('Missing email');
}
/** @var \Entity\User $user */
$user = Common::create_member_google([
'id' => $response['user_id'],
'email' => $response['email'],
'given_name' => '',
'family_name' => '',
]);
$user->login($this->session);
if ($user instanceof \Entity\User) {
echo json_encode( [ 'success' => true, 'user' => $user ] );
} else {
echo json_encode( [ 'success' => false, 'msg' => $user ] );
}
} catch(Exception $e) {
echo json_encode(['success' => false, 'msg' => $e->getMessage()]);
}
Приведенный выше код работает, если я удаляю $ client-> authenticate (); строка … Проблема в том, что я не могу получить имя_файла / фамилию и т. д. .. только email / google_user_id из tokeninfo …
Любые мысли о том, почему ключ работает для tokeninfo, но не для аутентификации?
Я пробовал много разных вариантов областей видимости .. как на стороне сервера, так и на стороне Android ..
$client->authenticate()
Метод не совсем делает то, что вы пытаетесь сделать. Он берет одноразовый код из предыдущей транзакции OAuth и обменивает его на токен доступа. В вашем случае — вы говорите, что у вас уже есть токен доступа.
Вы должны быть в состоянии позвонить $client->setAccessToken()
вместо этого установить токен, чтобы он мог выглядеть примерно так
$client->setAccessToken($_POST['google_access_token']);
Это решение я придумал после того, как пользователь 158443 предложил использовать $ client-> setAccessToken ();
// first json_encode the access token before sending it to $client->setAccessToken();
$json_encoded_access_token = json_encode([
'access_token' => $_POST['google_access_token'],
'created' => time(), // make up values for these.. otherwise the client thinks the token has expired..
'expires_in' => time()+60 // made up a value in the future...
]);
// and then set it
$client->setAccessToken($json_encoded_access_token);
// and then get userinfo or whatever you want from google api !! :)
$oauth2 = new \Google_Service_Oauth2($client);
$user_info = $oauth2->userinfo->get();
НОТА: вероятно, не очень разумно «эмулировать» expires_in и созданный, который я только что сделал, если вы работаете … Вы должны сначала вызвать tokeninfo и получить оттуда время истечения …
НОТА: Я до сих пор не знаю, как получить токен обновления для этого … но мне не нужен один для моего случая использования ..