问题描述
我有一个应用程序由于用户列表(https://content.googleapis.com/admin/directory/v1/users?orderBy=email&viewType=domain_public&maxResults=200&customer=my_customer&domain=XXX&key=XXX)不断返回而突然停止工作:
{
"error": {
"code": 403,"message": "Not Authorized to access this resource/api","errors": [
{
"message": "Not Authorized to access this resource/api","domain": "global","reason": "forbidden"
}
]
}
}
此应用程序提供给2个不同的域。它只对一个人有效,但对其他人无效。相同的代码...只是appId,apiKey和clientId发生了变化。我使用范围(https://www.googleapis.com/auth/admin.directory.user.readonly,https://www.googleapis.com/auth/admin.directory.user)配置了广域委派,还配置了API KEY,OAuth 2.0客户端。
我尝试重新创建整个项目,所有凭据,尝试使用http和https ...相同的错误。
API规范中是否有更改?我缺少什么了吗?
已编辑-请求源代码:
我只是复制了整个代码,使用凭据更改了“设置”,然后在浏览器控制台中执行了该操作。该代码可在身份验证之前或之后运行,但具有403响应:-(
// This first part I got from https://github.com/lord22shark/google
(function (__window) {
const Google = function (configuration,__callback) {
if ((!configuration) || !(configuration instanceof Object)) {
throw new Error('Google Api Wrapper - "configuration" must be defined!');
}
if ((!configuration.apiKey) || !(typeof(configuration.apiKey) === 'string') || (configuration.apiKey === '')) {
throw new Error('Google Api Wrapper - "apiKey" must be defined!');
}
if ((!configuration.discoveryDocs) || !(configuration.discoveryDocs instanceof Array) || (configuration.discoveryDocs.length === 0)) {
throw new Error('Google Api Wrapper - "discoveryDocs" must be a defined array!');
}
if ((!configuration.clientId) || !(typeof(configuration.clientId) === 'string') || (configuration.clientId === '')) {
throw new Error('Google Api Wrapper - "clientId" must be defined!');
}
if ((!configuration.scope) || !(typeof(configuration.scope) === 'string') || (configuration.scope === '')) {
throw new Error('Google Api Wrapper - "scope" must be defined!');
}
const thiz = this;
/**
*
*/
this.element = document.createElement('script');
this.element.type = 'text/javascript';
this.element.async = true;
this.element.defer = true;
this.element.src = 'https://apis.google.com/js/api.js';
/**
*
*/
this.element.onload = function () {
gapi.load('client:auth2',function () {
gapi.client.init({
'apiKey': configuration.apiKey,'discoveryDocs': configuration.discoveryDocs,'clientId': configuration.clientId,'scope': configuration.scope
}).then(function () {
thiz.googleAuthInstance = gapi.auth2.getAuthInstance();
// Listen for sign-in state changes.
// The callback function must be a global named function
thiz.googleAuthInstance.isSignedIn.listen(onUpdateGoogleSignInStatus);
thiz.setSigninStatus();
}).catch(function (error) {
__callback(error);
});
}.bind(thiz));
};
/**
*
*/
this.element.onreadystatechange = function () {
if (this.readyState === 'complete') {
this.onload();
}
};
/**
*
*/
this.setSigninStatus = function (isSignedIn) {
if ((isSignedIn === true) || (isSignedIn === undefined)) {
this.user = this.googleAuthInstance.currentUser.get();
this.authorized = this.user.hasGrantedScopes(configuration.scope);
this.authorizationToken = (this.authorized) ? this.user.getAuthResponse().access_token : null;
if (!this.authorized) {
this.googleAuthInstance.signIn().then(function (authenticatedUser) {
__callback(this.user,this.authorized,this.authorizationToken,this.googleAuthInstance);
}.bind(this)).catch(function (error) {
__callback(error);
});
} else {
__callback(this.user,this.googleAuthInstance);
}
}
};
/**
*
*/
this.getAuthInstance = function () {
return this.googleAuthInstance || null;
};
/**
*
*/
this.getUser = function () {
return this.user || null;
};
/**
*
*/
this.getAuthorizationToken = function () {
return this.authorizationToken;
};
/**
*
*/
this.getConfiguration = function () {
return configuration;
};
/**
*
*/
this.hasGrantedScopes = function () {
return this.authorized;
};
/**
*
*/
this.disconnect = function (deAuthenticate,callback) {
if (this.googleAuthInstance.isSignedIn.get()) {
if (deAuthenticate === true) {
this.googleAuthInstance.disconnect().then(function () {
if ((callback) && (callback instanceof Function)) {
callback(true);
}
});
} else {
this.googleAuthInstance.signOut().then(function () {
if ((callback) && (callback instanceof Function)) {
callback(false);
}
});
}
}
};
/**
*
*/
__window.onUpdateGoogleSignInStatus = function onUpdateGoogleSignInStatus (isSignedIn) {
this.setSigninStatus(isSignedIn);
}.bind(this);
document.body.appendChild(this.element);
};
__window.Google = Google;
})(window);
// This second part is part of my project - Settings
var settings = {
appId: 'xxx',apiKey: 'xxx',discoveryDocs: [
'https://www.googleapis.com/discovery/v1/apis/admin/directory_v1/rest'
],clientId: 'xxx',scope: 'https://www.googleapis.com/auth/admin.directory.user.readonly profile email'
};
var domains = [
'mydomain1.com','mydomain2.com'
];
// This is a bootstrap that I make some requests to sync @R_53_4045@ion retrieved from oauth2 and my application,where I make the API call after authorized
function bootstrap (google) {
if (google instanceof Error) {
console.log(google);
} else {
// Here I Start Angular angular.element(document).ready.... get the user domain...
var userDomain = 'mydomain1';
var profile = google.getUser().getBasicProfile();
console.log(profile);
gapi.client.directory.users.list({
'viewType': 'domain_public','customer': 'my_customer','maxResults': 200,'orderBy': 'email','domain': userDomain
}).then(function (response) {
console.log(response.result.users);
}).catch(function (error) {
console.log(error);
});
}
}
// Invokes Google with settings and if the authenticated user is part of one of my domains,I call "bootstrap" function
var google = new Google(settings,function (user,authorized,authorizationToken,authInstance) {
if (authorized !== undefined && authorizationToken !== undefined) {
var email = user.getBasicProfile().getEmail();
var allowed = domains.reduce(function (prevIoUs,current) {
if (email.indexOf(current) !== -1) {
prevIoUs += 1;
}
return prevIoUs;
},0);
if (allowed === 0) {
authInstance.disconnect();
bootstrap(new Error('User does not belong to XXX domain.'));
} else {
bootstrap(google);
}
} else {
bootstrap(new Error(user.details));
}
});
解决方法
解决方案
要运行users.list(),您应该是具有正确权限的管理员,因为Google Workspace管理员的类型不同。这就是为什么当您从超级管理员帐户运行代码时可以成功运行代码的原因,并且如果将viewType
设置为admin_view
也可以成功运行代码。
但是,虽然只能由管理员修改用户帐户,但域上的任何用户都可以读取用户个人资料(在您的情况下,这是可能的,因为您的方法是列出他们)。根据{{3}},要将viewType
设置为domain_public
,您必须首先为域启用documentation detailing this (具有联系人共享功能的个人用户禁用将不会被检索)。还请注意,https://www.googleapis.com/auth/admin.directory.user.readonly
以下范围应足够。
我希望这对您有所帮助。让我知道您是否需要其他任何东西,或者您是否不了解。 :)