Azure 函数:使用图形 API 时“访问令牌丢失或格式错误”

问题描述 投票:0回答:1

我正在开发一个与 Azure Active Directory Graph API (@azure/graph) 交互的 Azure Function。该函数 API 旨在验证电子邮件是否在 Azure AD(Entra Id)中注册和验证。但是,我遇到了访问令牌丢失或格式错误的问题。

当该函数尝试向 Graph API 发出请求以通过电子邮件获取用户时 (

graphClient.users.list
),它会抛出以下错误:

注意:我正在使用 postman 来测试 api

http://localhost:7071/api/checkEmail

Error verifying email: RestError: {"odata.error":{"code":"Authentication_MissingOrMalformed","codeForMetrics":"Authentication_MissingOrMalformed","message":{"lang":"en","value":"Access Token missing or malformed."}}} 

尽管使用 @azure/identity 中的 DefaultAzureCredential 来获取令牌,但仍会发生这种情况。 我已检查我的 Azure AD 配置和环境变量

(AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET)
,这似乎是正确的。

这是我的 Azure Function 代码的相关部分:

const { GraphRbacManagementClient } = require("@azure/graph");
const { DefaultAzureCredential } = require("@azure/identity");

const tenantId = process.env.AZURE_TENANT_ID;

module.exports = async function (context, req) {
    context.log('Checking if email is verified...');

    const { email } = req.body;

    if (!email) {
        context.res = {
            status: 400,
            body: "Please provide the email"
        };
        return;
    }

    try {
        const credential = new DefaultAzureCredential();
        const graphClient = new GraphRbacManagementClient(
            credential,
            tenantId
        );

        const verifyEmail = async (email) => {
            try {
                const users = await graphClient.users.list({ filter: `mail eq '${email}'` });
                const user = users.next().value;

                if (user) {
                    if (user.mailVerified) {
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            } catch (error) {
                console.error("Error verifying email:", error);
                return false;
            }
        };
        const isEmailVerified = await verifyEmail(email);

        if (isEmailVerified) {
            context.res = {
                status: 200,
                body: "Email is verified"
            };
        } else {
            context.res = {
                status: 400,
                body: "Email is not verified or does not exist"
            };
        }
    } catch (error) {
        console.error("Error:", error);
        context.res = {
            status: 500,
            body: "Internal Server Error"
        };
    }
};

此外,我已经尝试直接使用 ClientSecretCredential 而不是 DefaultAzureCredential,但问题仍然存在。 Azure AD 权限似乎已正确配置用于应用程序注册。

什么可能导致我的 Azure Functions 中出现“访问令牌丢失或格式错误”错误?如何确保正确获取访问令牌并将其用于通过 Graph API 进行身份验证?

任何见解或建议将不胜感激。谢谢!

javascript azure authentication azure-active-directory
1个回答
0
投票

根据您的错误代码,您的访问令牌是恶意的,尝试使用下面的代码使用Client Credentials Flow成功生成访问令牌:-

const axios = require('axios');

async function getToken(tenantId, clientId, clientSecret, scope) {
    try {
        const tokenEndpoint = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`;
        const requestBody = {
            client_id: clientId,
            scope: scope,
            client_secret: clientSecret,
            grant_type: 'client_credentials'
        };

        const response = await axios.post(tokenEndpoint, new URLSearchParams(requestBody), {
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
        });

        if (response.status === 200) {
            return response.data.access_token;
        } else {
            throw new Error('Failed to retrieve access token');
        }
    } catch (error) {
        console.error('Error getting token:', error.message);
        throw error;
    }
}


const tenantId = '8xxxxxxxx2395';
const clientId = 'cxxxxxxxxx5cb';
const clientSecret = 'vxxxxxxxNq9hD6bsf';
const scope = 'https://graph.microsoft.com/.default'; 

(async () => {
    try {
        const accessToken = await getToken(tenantId, clientId, clientSecret, scope);
        console.log('Access token:', accessToken);
        
    } catch (error) {
        console.error('Error:', error.message);
    }
})();

输出:-

访问令牌已成功生成:-

enter image description here

功能码:-

在下面的功能代码中使用上面的访问令牌:-

const { app } = require('@azure/functions'); const axios = require('axios'); // Define the HTTP trigger function app.http('httpTrigger1', { methods: ['GET', 'POST'], authLevel: 'anonymous', handler: async (request, context) => { context.log(`Http function processed request for url "${request.url}"`); try { // Fetch user profile from Microsoft Graph API const accessToken = 'xxxxxxxxxxxxxxqg'; // Replace with actual access token obtained using client credentials flow const userId = '8f1dbxxxxxx5e5d8f9a5d'; // Replace with the user's ID const profileResponse = await axios.get(`https://graph.microsoft.com/v1.0/users/${userId}`, { headers: { 'Authorization': `Bearer ${accessToken}` } }); // Return entire output from the profile response return { status: 200, body: profileResponse.data }; } catch (error) { context.log(`Error fetching user profile: ${error}`); return { status: 500, body: "Internal Server Error" }; } } });

输出:-

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.