简体   繁体   English

无权访问此资源/API (GCP)

[英]Not Authorized To Access This Resource/API (GCP)

I set up a service account with domain-wide delegation and I passed the client email, private key, scopes, and a user email the JWT method to impersonate a G-Suite user.我设置了一个具有域范围委托的服务帐户,并通过客户端电子邮件、私钥、范围和用户电子邮件通过 JWT 方法模拟 G-Suite 用户。 I then get specific user info from the Admin API and use it to create an email signature and push it to the Gmail API.然后,我从 Admin API 获取特定的用户信息,并使用它来创建电子邮件签名并将其推送到 Gmail API。 It works great if the user email I pass to the JWT method is a super admin but if I try to pass any other user I get an error response, "Not Authorized to access this resource/api".如果我传递给 JWT 方法的用户电子邮件是超级管理员,它会很好用,但如果我尝试传递任何其他用户,我会收到错误响应,“未授权访问此资源/api”。 Any ideas on how I can get it to work with a regular user account within my domain?关于如何让它与我域中的常规用户帐户一起工作的任何想法?

Here is the code.这是代码。 (genSignature.js) (genSignature.js)

const { google } = require('googleapis');
const privatekey = require('../private-key.json');

const scopes = [
    'https://www.googleapis.com/auth/gmail.settings.basic',
    'https://www.googleapis.com/auth/gmail.settings.sharing', 
    'https://www.googleapis.com/auth/admin.directory.user', 
    'https://www.googleapis.com/auth/admin.directory.user.readonly'
];

const auth = async (user) => {
    try {
        const jwtClient = new google.auth.JWT(
            privatekey.client_email,
            null, 
            privatekey.private_key,
            scopes,
            user // User who will be impersonated using the JWT client.
        );

        await jwtClient.authorize();
        return jwtClient;

    } catch (err) {

        console.log(err.message);

    };
};

function genSig(e) {

    auth(e).then((jwtClient) => {

        // Authenticate with the gmail API.
        const gmail = google.gmail({
            version: 'v1', 
            auth: jwtClient
        }); 

        // Authenticate with the admin API.
        const dir = google.admin({
            version: 'directory_v1', 
            auth: jwtClient
        });


        // Get users contact and job data from the directory. This data will be used as variables in their email signature. 
        dir.users.get({ userKey: e }, (err, response) => {
            if (err) {
                console.log(err.message);
            } else {
                let phones = response.data.phones;
                let workPhone = '';

                if (phones) {
                    for (i = 0; i < phones.length; i++) {
                        if (phones[i].type == 'work') {
                            workPhone = phones[i].value;
                        };
                    };
                };

                function getUserData() {
                    let userData = {
                        name: response.data.name.fullName, 
                        email: response.data.primaryEmail, 
                        phone: workPhone, 
                        avatar: response.data.thumbnailPhotoUrl, 
                        department: response.data.organizations[0].department, 
                        title: response.data.organizations[0].title
                    }; 
                    return userData;
                };

                let requestBody = {
                    signature: 'Test' 
                };

                // Update the users email signature for their primary email.
                gmail.users.settings.sendAs.update({ userId: e, sendAsEmail: e, requestBody }, (err, response) => {
                    if (err) {
                        console.log(err.message);
                    } else {
                        console.log(response.data);
                    };
                });
            };
        });
    });
}

module.exports = genSig;

(signatures.js) (签名.js)

const express = require('express');
const router = express.Router();
const genSig = require('../../functions/genSignature');

// Get webhooks from Google.
router.post('/', (req, res) => {

    let email = req.body.email;
    let emailStr = email.toString();
    console.log(emailStr);
    genSig(emailStr);


    res.status(200).json({
        "msg": "data recieved..."
    });
});

module.exports = router;

(index.js) (index.js)

const express = require('express');
const app = express();

app.use(express.json());
app.use('/email-signature', require('./routes/api/signatures'));

const PORT = process.env.PORT || 6000;

app.listen(PORT, () => console.log(`Server is running on port ${PORT}`));

Here are some screenshots.这是一些屏幕截图。

API configuration on G-Suite G-Suite 上的 API 配置

Service Account Setup服务帐户设置

Successful request vs unsuccessful request成功的请求与不成功的请求

You need to impersonate an admin:您需要模拟管理员:

Only accounts with User Management privileges (like a Super Admin, or a User Management Admin) can access Users: get .只有具有用户管理权限的帐户(如超级管理员或用户管理管理员)才能访问用户:获取. You have to take into account that this is part of Admin SDK , which is to be used by admin accounts.您必须考虑到这是Admin SDK的一部分,供管理员帐户使用。

You can also check this is not possible if you try calling this via Try this API on the reference docs (you'll get the same message: Not Authorized to access this resource/api ).如果您尝试通过参考文档上的Try this API调用它,您还可以检查这是不可能的(您将收到相同的消息: Not Authorized to access this resource/api )。

It doesn't matter that you're using a Service Account with domain-wide authority: when the service account is impersonating another user, it can only access the resources this user can access .使用具有域范围权限的服务帐户并不重要:当服务帐户模拟另一个用户时,它只能访问该用户可以访问的资源

Solution:解决方案:

In this case, the impersonated account should have user management privileges if you want to retrieve user data from Admin SDK.在这种情况下,如果您想从 Admin SDK 检索用户数据,则模拟帐户应具有用户管理权限。

But since these privileges are not necessary for calling the Gmail API method, you could impersonate an admin account when calling Users: get , and a regular one when calling users.settings.sendAs.update .但是由于调用 Gmail API 方法不需要这些权限,因此您可以在调用Users: get时模拟一个管理员帐户,并在调用users.settings.sendAs.update时模拟一个普通帐户。

Reference:参考:

this is not a new post.这不是一个新帖子。 However, I faced it and found a solution.但是,我面对它并找到了解决方案。

You can use a service account by assigning a role.您可以通过分配角色来使用服务帐户。 See "Assign a role to a service account" in Assign specific admin role .请参阅分配特定管理员角色中的“将角色分配给服务帐户”。 There are details in updates blog post. 更新博客文章中有详细信息。

At first, you need to create a custom admin role at Google Workspace Admin Console.首先,您需要在 Google Workspace 管理控制台中创建一个自定义管理员角色。 And you can assign service accounts to the custom admin role with email address.您可以使用电子邮件地址将服务帐户分配给自定义管理员角色。

It worked on Google Cloud Functions in my environment.它在我的环境中适用于 Google Cloud Functions。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 尝试访问目录api时无权访问此资源/ api - Not Authorized to access this resource/api while trying to access directory api users.list返回403错误:未获得访问此资源/ api的权限 - users.list returns 403 Error: Not Authorized to access this resource/api AWS 用户无权通过显式拒绝访问此资源 - AWS User is not authorized to access this resource with an explicit deny 为什么 changeResourceRecordSets 无权访问此资源? - Why changeResourceRecordSets gets not authorized to access this resource? 如何禁止非授权用户访问API? - How to prohibit access to the API for non authorized users? REST API URI 是否应该根据参数授权,而不仅仅是资源? - Should REST API URIs be authorized based on the parameters, not just the resource? 您无权访问此页面Odesk api node.js - You are not authorized to access this page Odesk api node.js 仅对我授权的客户端应用程序限制API访问 - Restrict API access only for my authorized client applications 如何使用 Express.js 限制 API 仅访问授权域? - How to restrict API access to only authorized domains using Express.js? 有哪些方法可以返回用户有权使用 REST API 访问的资源子集? - What are some methods for returning a subset of resources user is authorized to access with a REST API?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM