Это была такая большая головная боль - заставить мою учетную запись службы проходить аутентификацию в том же веб-приложении, где у меня есть пользователи, которые также входят в систему через oauth2.
Так что мне интересно, это вообще возможно?
Если нет, стоит ли просто придерживаться учетной записи службы?Нужно ли аутентифицировать пользователей по старому стилю?Хаха
Спасибо.
Что касается служебной учетной записи, я включил широкое делегирование домена , включил клиентский ключ + область API в моей консоли администратора G Suite и получил пример php с работающим API книг.,Однако всякий раз, когда я пробую любой другой API, кроме книг, я получаю сообщение об ошибке,
клиент не авторизован для получения токенов доступа, используя этот метод
ОБНОВЛЕНИЕ: Я попытался использовать пример @ dalmto и добавил несколько строк для проверки API gmail, например:
putenv('GOOGLE_APPLICATION_CREDENTIALS=credentials.json');
$user = 'email@domain.de';
function getGoogleClient() {
return getServiceAccountClient();
}
function getServiceAccountClient() {
try {
// Create and configure a new client object.
$client2 = new Google_Client();
$client2->useApplicationDefaultCredentials();
$client2->setScopes(array('https://www.googleapis.com/auth/userinfo.email','https://www.googleapis.com/auth/admin.directory.user.readonly','https://www.googleapis.com/auth/userinfo.profile','https://www.googleapis.com/auth/gmail.readonly','https://www.googleapis.com/auth/calendar'));
$client2->setAccessType('offline');
$client2->setSubject($user);
return $client2;
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
$newGoogleClient = getGoogleClient();
$service3 = new Google_Service_Gmail($newGoogleClient);
$results3 = $service3->users_labels->listUsersLabels($user);
Но сейчас я просто получаю ошибки "400: Bad Request"
РЕДАКТИРОВАТЬ : После еще нескольких копаний появляется примечание: ' failedPrecondition ' - есть какая-нибудь идея, которая может быть предварительным условием?Я разрешил следующие области для клиента в моей консоли администратора:
hxxps: //www.googleapis.com/auth/gmail.metadata, hxxps: //www.googleapis.com/auth / userinfo.email, hxxps: //www.googleapis.com/auth/userinfo.profile, hxxps: //www.googleapis.com/auth/gmail.modify, hxxps: //www.googleapis.com/auth/gmail.readonly,
hxxps: //www.googleapis.com/auth/gmail.labels,
hxxps: //mail.google.com/
И включил API ивключил область действия на экране «OAuth Consent»
DWD также включен: Снимок экрана «Обзор учетной записи службы»
EDIT2 : Хорошо, я нашелотсутствующим предварительным условием был «setSubject».
Как только я добавил, что это пошло еще дальше, но все еще не удалось снова на '"error": "unauthorized_client",\n "error_description": "Client is unauthorized to retrieve access tokens using this method.'
К вашему сведению: при создании учетной записи службы я назначил ей роль «проект -> владелец».Этого достаточно?Нужно ли добавлять еще?
EDIT3 : Я также только что проверил регистратор, и он говорит, что DWD включен .. Я на моем конце здесь хаха
client: {
adminState: {
updateTime: "2018-11-23T00:29:44.810Z"
}
assertionMatchExistingGrant: "MATCH_GRANT_DISABLED"
authType: "PUBLIC_KEY"
brandId: "aaaaaaaaaaaaaa"
clientId: "aaaaaaaaaaaaaaaaaa"
consistencyToken: "2018-11-23T00:29:44.953175Z"
creationTime: "2018-11-23T00:29:44.810Z"
displayName: "Client for servicemaint1"
domainWideDelegation: "DELEGATION_ENABLED"
projectNumber: "aaaaaaaaaaaaaaaa"
threeLeggedOauth: "DISABLED"
updateTime: "2018-11-23T00:29:44.953175Z"
}
РЕДАКТИРОВАТЬ 4: НАКОНЕЦ РАБОТЫ!
Так что я пробовал это в новом проекте, который я создал для тестирования все утро / вчера вечером.Но моя аутентификация пользователя oauth2 проходила через другой проект (где я также не мог заставить служебную учетную запись работать все утро / день вчерашнего дня).
Так или иначе, я заметил в: https://myaccount.google.com/permissions«Приложения с доступом к вашей учетной записи» - только мой старый проект / приложение было авторизовано.Поэтому я вернулся к своему первому проекту, создал новый файл идентификатора клиента учетной записи службы .json, и он, наконец, сработал для аутентификации обоих!:)
Я должен был разрешить это где-то дополнительно по линии, которую я не сделал со вторым проектом.
Еще раз спасибо.
EDIT5: Еще один быстрый вопрос - это правильный способ сделать это в стеке потока?С постоянно возвращаясь к редактированию?
Также для других, кто сталкивается с этим позже, вот мой полный блок аутентификации (извините, он немного длинный):
putenv('GOOGLE_APPLICATION_CREDENTIALS=maintenanceapp.json');
$user = 'xyz@abc.com';
function getGoogleClient() {
return getServiceAccountClient();
}
function getServiceAccountClient() {
$user = 'xyz@abc.com';
try {
// Create and configure a new client object.
$client2 = new Google_Client();
$client2->useApplicationDefaultCredentials();
$client2->setScopes(['https://www.googleapis.com/auth/gmail.metadata','https://www.googleapis.com/auth/userinfo.email','https://www.googleapis.com/auth/userinfo.profile','https://www.googleapis.com/auth/gmail.modify','https://www.googleapis.com/auth/gmail.readonly','https://www.googleapis.com/auth/gmail.labels']);
//$client2->setAccessType('offline');
$client2->setSubject($user);
return $client2;
} catch (Exception $e) {
echo "An error occurred: " . $e->getMessage();
}
}
$newGoogleClient = getGoogleClient();
$service3 = new Google_Service_Gmail($newGoogleClient);
$results3 = $service3->users_labels->listUsersLabels($user);
/*************************************************
* Ensure you've downloaded your oauth credentials
************************************************/
if (!$oauth_credentials = getOAuthCredentialsFile()) {
echo missingOAuth2CredentialsWarning();
return;
}
/************************************************
* NOTICE:
* The redirect URI is to the current page, e.g:
* http://localhost:8080/idtoken.php
************************************************/
$redirect_uri = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
$client = new Google_Client();
// USER AUTH
$client->setAuthConfig($oauth_credentials);
$client->setRedirectUri($redirect_uri);
$client->setScopes(array('https://www.googleapis.com/auth/userinfo.email','https://www.googleapis.com/auth/userinfo.profile','https://www.googleapis.com/auth/gmail.readonly','https://www.googleapis.com/auth/calendar'));
$client->setApprovalPrompt('auto');
$client->setAccessType('offline');
$plus = new Google_Service_Plus($client);
/************************************************
* If we're logging out we just need to clear our
* local access token in this case
************************************************/
if (isset($_REQUEST['logout'])) {
unset($_SESSION['id_token_token']);
}
/************************************************
* If we have a code back from the OAuth 2.0 flow,
* we need to exchange that with the
* Google_Client::fetchAccessTokenWithAuthCode()
* function. We store the resultant access token
* bundle in the session, and redirect to ourself.
************************************************/
if (isset($_GET['code'])) {
$token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
// store in the session also
$_SESSION['id_token_token'] = $token;
// redirect back to the example
header('Location: https://abc.de/index.php');
// return;
}
/************************************************
If we have an access token, we can make
requests, else we generate an authentication URL.
************************************************/
if (
!empty($_SESSION['id_token_token'])
&& isset($_SESSION['id_token_token']['id_token'])
) {
$client->setAccessToken($_SESSION['id_token_token']);
} else {
$authUrl = $client->createAuthUrl();
//header('Location: ' . $authUrl);
}
/************************************************
If we're signed in we can go ahead and retrieve
the ID token, which is part of the bundle of
data that is exchange in the authenticate step
- we only need to do a network call if we have
to retrieve the Google certificate to verify it,
and that can be cached.
************************************************/
if ($client->getAccessToken()) {
$token_data = $client->verifyIdToken();
}