让我的服务帐户在我也有用户也通过oauth2登录的同一Webapp上进行身份验证非常令人头疼。
所以我想知道,这有可能吗?
如果没有,应该坚持使用服务帐户吗?然后,是否需要按照自己的身份(旧式学校)对用户进行身份验证?哈哈
谢谢。
关于服务帐户,我已经在我的G Suite管理控制台中启用了全域delegation,启用了客户端密钥+ api范围,并获得了使书籍api工作的php示例。但是,只要我尝试使用除书籍以外的其他任何api,都会收到错误消息
未授权客户端使用此方法检索访问令牌
更新:我尝试使用@dalmto的示例,并添加了几行测试gmail api,例如:
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:错误的请求”错误
编辑:在进行进一步的挖掘后,有一个注释:' 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/
并在“ OAuth同意屏幕”中启用了api并启用了作用域
还启用了DWD:Service Account Overview Screenshot
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"
}
EDIT4:终于可以了!
因此,我在一个为整个上午/昨晚进行测试而创建的新项目中一直在尝试此操作。但是我的oauth2用户身份验证是通过另一个项目运行的(昨天早上/下午我也无法使服务帐户正常工作)。
因此,无论如何,我注意到:https://myaccount.google.com/permissions“具有访问您帐户权限的应用程序”-仅授权了我的旧项目/应用程序。因此,我回到了我的第一个项目,创建了一个新的服务帐户客户端ID .json文件,它终于可以对两者进行身份验证了! :)
我必须已经授权该权限,这是我在第二个项目中没有做过的。
再次感谢。
EDIT5:还有一个快速问题-这是在stackoverflow上执行此操作的正确方法吗?随着不断地回去编辑?
另外,对于其他后来迷失于此的人,这是我的总身份验证块(抱歉,它有点长):
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();
}
答案 0 :(得分:0)
在google开发人员控制台中,当您创建项目和凭据时,必须选择要为哪种类型的应用程序创建哪种类型的客户端。
有几种不同的方法可以向Google进行身份验证。
使用这些客户端的代码也不同。您无法创建Web OAuth2客户端并将其用于用于调用服务帐户的代码。
“客户端未经授权使用此方法检索访问令牌”。
确切地说。您在Google Developer Console上设置的客户端不是服务帐户客户端,或者您使用的代码不适用于服务帐户客户端。
这是我的serviceaccount.php示例。如果您的代码需要看起来像这样,并且需要确保您在google开发者控制台上创建的客户端是服务帐户客户端。
require_once __DIR__ . '/vendor/autoload.php';
// Use the developers console and download your service account
// credentials in JSON format. Place the file in this directory or
// change the key file location if necessary.
putenv('GOOGLE_APPLICATION_CREDENTIALS='.__DIR__.'/service-account.json');
/**
* Gets the Google client refreshing auth if needed.
* Documentation: https://developers.google.com/identity/protocols/OAuth2ServiceAccount
* Initializes a client object.
* @return A google client object.
*/
function getGoogleClient() {
return getServiceAccountClient();
}
/**
* Builds the Google client object.
* Documentation: https://developers.google.com/api-client-library/php/auth/service-accounts
* Scopes will need to be changed depending upon the API's being accessed.
* array(Google_Service_Analytics::ANALYTICS_READONLY, Google_Service_Analytics::ANALYTICS)
* List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
* @return A google client object.
*/
function getServiceAccountClient() {
try {
// Create and configure a new client object.
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope([YOUR SCOPES HERE]);
return $client;
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
开发者控制台
在客户端下,检查您正在使用的客户端是否可以在服务帐户密钥下找到。如果不是,则它是错误的客户端类型,将无法与您的代码一起使用。创建一个新的服务帐户客户端,并使用该客户端ID设置域范围内的委派。
答案 1 :(得分:0)
response_type=code
client_id=348268306866-9dl0kdgn2f9bjhoge7pris1jo8u9si47.apps.googleusercontent.com
redirect_uri=https://degoo.com/me/googleoauth2callback
access_type=offline
scope=https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/contacts.readonly
state={"RedirectUrl":"/me/chooseaccount","RegisterIfNotExists":true}
这就是我们所知道的。