问题描述
我正在尝试编写一个调用 Microsoft Graph API 的简单 Azure 函数.但我无法使 access_token 工作.这是我所做的:
I'm trying to write a simple Azure Function that calls the Microsoft Graph API. But I could not make the access_token work. Here is what I've done:
- 从 Azure 门户创建了一个新的 Azure Function App
- 开启应用服务身份验证"设置,并指示其使用 AAD 登录(管理模式为 Express).
- 将应用配置为具有 Microsoft Graph 的登录并读取用户配置文件"等委派权限.
- 创建了一个新的 JavaScript 函数 HttpTriggerJS1
- 将此功能的授权级别更改为匿名"(否则默认情况下功能"级别甚至不允许我运行该功能,总是返回 401 Unauthorized)
- 安装了必要的 Node 模块(
npm install request
) 以及实际功能:
- Created a new Azure Function App from the Azure Portal
- Turned on the "App Service Authentication" setting and instructed it to sign in with AAD (management mode is Express).
- Configured the app to have delegated permissions like "Sign in and read user profile" for Microsoft Graph.
- Created a new JavaScript function HttpTriggerJS1
- Changed the authorization level of this function to "Anonymous" (otherwise by default the "Function" level would not even allow me to run the function, always returning 401 Unauthorized)
- Installed the necessary Node module (
npm install request
) And the actual function:
var request = require('request');
module.exports = function (context, req) {
var token = req.headers['x-ms-token-aad-access-token'];
var reqUrl = 'https://graph.microsoft.com/v1.0/me/';
request.get(reqUrl, {'auth': {'bearer': token}}, function (err, response, msg) {
context.res = {
body: msg
};
context.done();
});
};
在单独的浏览器窗口中测试了此功能.让我正确登录到 AAD.
Tested this function in a separate browser window. Signed me in to AAD correctly.
但是Graph返回的信息是:
But the message returned from Graph was:
"{
"error": {
"code": "InvalidAuthenticationToken",
"message": "CompactToken parsing failed with error code: -2147184105",
"innerError": {
"request-id": "4c78551d-f0fe-4104-b1d3-e2d96fd3c02c",
"date": "2017-05-16T19:11:14"
}
}
}"
我查看了从 req.headers['x-ms-token-aad-access-token']
获得的令牌.它有点像AQABAA....",这似乎与我之前看到的以eyJ...."开头的常规 access_token 不同.
I looked into the token I got from req.headers['x-ms-token-aad-access-token']
. It's something like "AQABAA....", which seems different from the regular access_token I've seen before that starts with "eyJ....".
这里可能有什么问题?调用 Graph API 时,我应该使用请求标头中的 access_token 吗?
What could be wrong here? When calling the Graph API, am I supposed to be using the access_token from the request headers?
谢谢!
根据 Chris Gillum 的建议,我还研究了代表"流程.这是我更新的函数,它获取特定资源的 access_token (https://graph.microsoft.com 在我的情况下)通过提供 id_token(从请求标头中检索).:
According to Chris Gillum's suggestion, I also looked into the "on-behalf-of" flow. And here is my updated function, which acquires an access_token for a particular resource (https://graph.microsoft.com in my case) by providing the id_token (retrieved from the request headers).:
var request = require('request');
module.exports = function (context, req) {
var parameters = {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
client_id: process.env.WEBSITE_AUTH_CLIENT_ID,
client_secret: process.env.WEBSITE_AUTH_CLIENT_SECRET,
assertion: req.headers['x-ms-token-aad-id-token'],
resource: 'https://graph.microsoft.com',
requested_token_use: 'on_behalf_of'
};
request.post('https://login.microsoftonline.com/microsoft.com/oauth2/token', {form: parameters}, function (aadErr, aadResponse, aadMsg) {
var msgJson = JSON.parse(aadMsg);
request.get('https://graph.microsoft.com/v1.0/me/', {'auth': {'bearer': msgJson.access_token}}, function (err, response, msg) {
context.res = {
body: msg
};
context.done();
});
});
};
推荐答案
在使用 Azure 应用服务身份验证/授权时,您可以通过两种方式来完成这项工作:
There are two ways you can make this work when using Azure App Service Authentication / Authorization:
- 在函数应用的 AAD 配置中分配默认资源.
- 使用 AAD 代表流程 将您的 ID 令牌 (
x-ms-token-aad-id-token
) 交换为 MS Graph 访问令牌.
- Assign a default resource in your function app's AAD configuration.
- Use the AAD on-behalf-of flow to exchange your ID token (
x-ms-token-aad-id-token
) for an MS Graph access token.
不需要任何代码更改的最简单方法是执行 #1.我在 App Service Auth 和 AzureAD Graph API 博客文章(需要一些更新),但我会在此处为您提供 Microsoft Graph 的函数优化版本.
The simplest approach which doesn't require any code changes is to do #1. I outline the process in my App Service Auth and the Azure AD Graph API blog post (which needs some updates), but I'll give you the Functions-optimized version for the Microsoft Graph here.
你需要做的主要事情是:
The main things you need to do are:
- 确保您的 AAD 设置包含客户端密码(您已经拥有该密码).
- 确保您的 AAD 设置有权访问 Microsoft Graph(您已经这样做了).
- 在资源浏览器中打开您的函数应用(使用平台设置下的门户中的链接strong>),导航到左侧面板上的 config/authsettings,将
"additionalLoginParams"
从null
更改为["resource=https://graph.microsoft.com"]
,然后保存更改.
- Ensure your AAD settings include a client-secret (you already have this).
- Ensure your AAD settings have the permissions to access the Microsoft Graph (you have already done this).
- Open your function app in Resource Explorer (use the link in the portal under Platform Settings), navigate to config/authsettings on the left-hand panel, change
"additionalLoginParams"
fromnull
to["resource=https://graph.microsoft.com"]
, and save the changes.
执行此操作并再次登录后,x-ms-token-aad-access-token
请求标头将始终为您提供适用于 Microsoft Graph 的访问令牌.
After doing this and logging in again, the x-ms-token-aad-access-token
request header will always give you an access token that works with the Microsoft Graph.
上述方法的缺点是,如果您需要从函数应用访问多个受 AAD 保护的资源,它对您没有帮助.如果这对您来说是个问题,那么您需要使用上面的方法 #2.
The disadvantage of the above approach is that it doesn't help you if you need to access more than one AAD-protected resource from your function app. If that's a problem for you, then you'll need to use approach #2 above.
这篇关于从 Azure Functions 内部调用 Microsoft Graph API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!