Поскольку аутентификация входа в систему Google отключена с прошлой недели, я пытаюсь настроить oAuth 2.0 на учетную запись службы. Мы хотим предоставить пользователям нашего внутреннего веб-приложения возможность выхода из офиса.
Я скачал последний Клиентская библиотека Google API для PHP. в Консоль разработчика Google, Я создал новый проект для своего приложения и создал Service account
полномочия. Я также включил службу API: Admin SDK
в консоли разработчика.
Я предоставил ID пользователя учетной записи доступ к правильным областям (я думаю):
Когда я использую пример service-account.php и изменяю детали, я получаю JSON с токеном доступа, но когда я делаю запрос CURL (такой же, как и раньше), чтобы получить настройки электронной почты от пользователя, возникает ошибка "You are not authorized to access this API."
происходят.
Мой код:
<?php
include_once "templates/base.php";
require_once realpath(dirname(__FILE__) . '/../src/Google/autoload.php');
$client_id = '124331845-DELETEDPART-hbh89pbgl20citf6ko.apps.googleusercontent.com'; //Client ID
$service_account_name = '124331845-DELETEDPART-89pbgl20citf6ko@developer.gserviceaccount.com'; //Email Address
$key_file_location = 'globaltext-4ce09b20cb73.p12'; //key.p12
$client = new Google_Client();
if (isset($_SESSION['service_token'])) {
$client->setAccessToken($_SESSION['service_token']);
}
$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
array('https://apps-apis.google.com/a/feeds/emailsettings/2.0/'),
$key
);
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$aOutput = json_decode($client->getAccessToken());
$strEmailAdresSplit = explode('@', "[email protected]");
$strDomein = $strEmailAdresSplit[1];
$strAlias = $strEmailAdresSplit[0];
$resConnectionJobs = curl_init();
$aHeader = array();
$aHeader[] = 'Authorization: Bearer '.$aOutput->access_token;
$aHeader[] = 'Content-Type: application/atom+xml';
curl_setopt($resConnectionJobs, CURLOPT_URL, "https://apps-apis.google.com/a/feeds/emailsettings/2.0/DOMAIN.EXTENSION/FIRSTNAME.LASTNAME/vacation");
curl_setopt($resConnectionJobs, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($resConnectionJobs, CURLOPT_HTTPHEADER, $aHeader);
curl_setopt($resConnectionJobs, CURLOPT_RETURNTRANSFER, true);
curl_setopt($resConnectionJobs, CURLOPT_HEADER, false);
$oCurlData = curl_exec($resConnectionJobs);
curl_close($resConnectionJobs);
echo $oCurlData;
?>
Вы уверены, что ваши учетные данные в порядке?
Пожалуйста, попробуйте следующую процедуру, чтобы убедиться, что у вас есть правильные учетные данные.
Создание ваших ключей API
Перейти к консоль разработчика и выполните следующие действия:
Получение токена доступа & обновить токен
Создайте файл, который содержит следующий код:
<?php
if (isset($_GET['code'])) {
// try to get an access token
$code = $_GET['code'];
$url = 'https://accounts.google.com/o/oauth2/token';
$params = array(
"code" => $code,
"client_id" => YOUR_CLIENT_ID,
"client_secret" => YOUR_CLIENT_SECRET,
"redirect_uri" => 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"],
"grant_type" => "authorization_code");
$ch = curl_init();
curl_setopt($ch, constant("CURLOPT_" . 'URL'), $url);
curl_setopt($ch, constant("CURLOPT_" . 'POST'), true);
curl_setopt($ch, constant("CURLOPT_" . 'POSTFIELDS'), $params);
$output = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
if ($info['http_code'] === 200) {
header('Content-Type: ' . $info['content_type']);
return $output;
} else {
return 'An error happened';
}
} else {
$url = "https://accounts.google.com/o/oauth2/auth";
$params = array(
"response_type" => "code",
"client_id" => YOUR_CLIENT_ID,
"redirect_uri" => 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"],
"scope" => "https://www.googleapis.com/auth/plus.me");
$request_to = $url . '?' . http_build_query($params);
header("Location: " . $request_to);
}
Теперь замени YOUR_CLIENT_ID
а также YOUR_CLIENT_SECRET
с вашим идентификатором клиента и секретом клиента.
Убедитесь, что ваш объем правильный. Например, это должно быть https://www.googleapis.com/auth/analytics
если вы хотите получить доступ к Google Analytics.
Если вы запустите файл, вы должны получить экран подтверждения OAuth2.
Если вы сейчас нажмете Accept
, вы должны получить результат, который выглядит следующим образом:
{
"access_token" : YOUR_ACCESS_TOKEN,
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : YOUR_REFRESH_TOKEN
}
Результат может содержать дополнительные поля, в зависимости от того, на какую область вы претендуете.
Подключение к системам Google в фоновом режиме
После того, как вышеперечисленное заработало, ваше приложение должно реализовать следующий рабочий процесс:
1) Проверьте, содержит ли ваш ввод параметр GET с именем «code». Если присутствует «код», получите новый токен доступа и повторите этот шаг (обновите страницу)
Если «код» отсутствует, перейдите к шагу 2.
2) Проверьте, хранятся ли у вас учетные данные для вашего сервиса. Если учетные данные присутствуют, проверьте, не истек ли ваш токен доступа или скоро истекает. Затем перейдите к шагу 3. Если учетные данные отсутствуют, перейдите к пути авторизации вашей службы, чтобы получить код авторизации, и вернитесь к шагу 1 (убедитесь, что Google перенаправляет на ваш текущий URL).
3) Если требуется обновление, обновите страницу и вернитесь к шагу 1.
Если обновление не требуется, вы готовы сделать то, что вы хотели сделать в первую очередь.
Однако PHP-библиотека Google позаботится о том, чтобы поток oAuth2 для вас. Если вы используете их библиотеку, каждая из трехэтапных процедур выполняется библиотекой, и вы сразу же сможете делать все, что захотите, со службами Google. Я сам использую эту стратегию в моя панель инструментов Google Adwords.
Однако вы можете просто написать свою собственную библиотеку и напрямую подключиться к сервису. Ниже приведен код разработчика из проекта, который я написал несколько месяцев назад. Хотя он не работает «из коробки» (поскольку это контроллер, являющийся частью более крупного приложения), он должен помочь вам понять поток, который библиотека Google берет на себя.
namespace Application;
class Controller_API_Google_Youtube extends Controller_API {
public function read() {
$scope = "https://www.googleapis.com/auth/youtube";
$this->doOauth($scope);
}
function doOauth($scope) {
$oauth2Credentials = JSON_File::load(__DIR__ . DIRECTORY_SEPARATOR . 'Config.json');
$paths = array(
'token' => 'https://accounts.google.com/o/oauth2/token',
'auth' => "https://accounts.google.com/o/oauth2/auth");
$refreshtime = 300;
if (isset($_GET['code'])) {
// Get access code
$query = $_GET;
unset($query['code']);
if (count($query) > 0) {
$query = '?' . http_build_query($query);
} else {
$query = '';
}
$client = \PowerTools\HTTP_Client::factory(
array(
'maps' => array(
'url' => $paths['token'],
'returntransfer' => 1,
'post' => true,
'postfields' => array(
'code' => $_GET['code'],
"client_id" => $oauth2Credentials['client_id'],
"client_secret" => $oauth2Credentials['client_secret'],
"redirect_uri" => HTTP_PROTOCOL . URL_PATH . $query,
"grant_type" => "authorization_code")
)
)
)->execute();
$responses = $client->getResponses();
$response = array_pop($responses);
$info = $response['maps']->getInfo();
$content = $response['maps']->getContent();
if ($info['http_code'] === 200) {
$output = JSON::decode($content);
$oauth2Credentials[$scope] = array();
$oauth2Credentials[$scope]['expires'] = time() + $output['expires_in'];
$oauth2Credentials[$scope]['access_token'] = $output['access_token'];
$oauth2Credentials[$scope]['refresh_token'] = $output['refresh_token'];
file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . 'Config.json', JSON::encode($oauth2Credentials));
header("Location: " . HTTP_PROTOCOL . URL_PATH . $query);
} else {
echo "Something went wrong";
}
} elseif (!isset($oauth2Credentials[$scope])) {
// Get auth code
header("Location: " . $paths['auth'] . '?' . http_build_query(
array(
"response_type" => "code",
"client_id" => $oauth2Credentials['client_id'],
"redirect_uri" => HTTP_PROTOCOL . DOMAIN_PATH,
"scope" => $scope
)
));
} elseif ($oauth2Credentials[$scope]['expires'] - $refreshtime < time()) {
// Refresh access code
$client = \PowerTools\HTTP_Client::factory(
array(
'maps' => array(
'url' => $paths['token'],
'returntransfer' => 1,
'post' => true,
'postfields' => array(
"client_id" => $oauth2Credentials['client_id'],
"client_secret" => $oauth2Credentials['client_secret'],
"refresh_token" => $oauth2Credentials[$scope]['refresh_token'],
"grant_type" => "refresh_token")
)
)
)->execute();
$responses = $client->getResponses();
$response = array_pop($responses);
$info = $response['maps']->getInfo();
$content = $response['maps']->getContent();
if ($info['http_code'] === 200) {
$output = JSON::decode($response['maps']->getContent());
$oauth2Credentials[$scope]['expires'] = time() + $output['expires_in'];
$oauth2Credentials[$scope]['access_token'] = $output['access_token'];
file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . 'Config.json', JSON::encode($oauth2Credentials));
$this->read();
} else {
$this->output = array("error" => "Something went wrong");
}
} else {
$this->doSomethinguseful($oauth2Credentials, $scope);
}
return $this;
}
function doSomethinguseful($oauth2Credentials, $scope) {
// https://developers.google.com/youtube/v3/sample_requests?hl=nl
$client = \PowerTools\HTTP_Client::factory(
array(
'maps' => array(
'useragent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13',
'url' => 'https://www.googleapis.com/youtube/v3/channels?part=contentDetails&mine=true',
'returntransfer' => true,
'httpheader' => array(
'Authorization: Bearer ' . $oauth2Credentials[$scope]['access_token'],
'Accept-Encoding: gzip, deflate'
)
)
)
)->execute();
$responses = $client->getResponses();
$response = array_pop($responses);
$content = $response['maps']->getContent();
$this->output = JSON::decode(gzdecode($content));
}
}
Похоже, у вас тоже может быть проблема.
Призыв к Google_Auth_AssertionCredentials
на самом деле требует больше параметров, чем вы посылаете для работы с учетной записью службы. (По крайней мере, так и было в моем случае.)
Вам нужно передать достаточно параметров, чтобы включить подпрограмму (какого пользователя выполнять действия из-за).
Без этого мне всегда отказывали в доступе. Это явно не очевидно, так как в библиотеку php даже была добавлена функция, loadServiceAccountJson
, который должен установить клиентское соединение с учетной записью службы, но разрывается, потому что он также не устанавливает sub.
Смотрите рабочий код здесь: Google php клиентская библиотека loadServiceAccountJson не работает — исправлено