教程:在 Node.js 控制台守护程序应用中调用 Microsoft 图形 API
在本教程中,你将构建一个控制台守护程序应用,该应用使用其自己的身份调用 Microsoft 图形 API。 构建的守护程序应用使用适用于 Node.js 的 Microsoft 身份验证库 (MSAL)。
请按照本教程中的步骤进行操作:
- 在 Azure 门户中注册应用程序
- 创建 Node.js 控制台守护程序应用项目
- 向应用添加身份验证逻辑
- 添加应用注册详细信息
- 添加方法来调用 web API
- 测试应用程序
先决条件
- Node.js
- Visual Studio Code 或其他代码编辑器
注册应用程序
首先,请完成向 Microsoft 标识平台注册应用程序中的步骤来注册你的应用。
对于应用注册,请使用以下设置:
- 名称:
NodeDaemonApp
(建议) - 支持的帐户类型:仅此组织目录中的帐户
- API 权限:Microsoft API>Microsoft Graph>应用程序权限>
User.Read.All
- 客户端机密:
*********
(记录此值以便在后面的步骤中使用 - 它只显示一次)
创建项目
首先为此 Node.js 教程项目创建一个目录。 例如 NodeDaemonApp。
在终端中,切换到你创建的目录(项目根目录),然后运行以下命令:
npm init -y npm install --save dotenv yargs axios @azure/msal-node
接下来,编辑项目根目录中的 package.json 文件,并在
main
的值前面加上bin/
,如下所示:"main": "bin/index.js",
现在,创建 bin 目录,并在 bin 内,将以下代码添加到名为 index.js 的新文件中 :
#!/usr/bin/env node // read in env settings require('dotenv').config(); const yargs = require('yargs'); const fetch = require('./fetch'); const auth = require('./auth'); const options = yargs .usage('Usage: --op <operation_name>') .option('op', { alias: 'operation', describe: 'operation name', type: 'string', demandOption: true }) .argv; async function main() { console.log(`You have selected: ${options.op}`); switch (yargs.argv['op']) { case 'getUsers': try { // here we get an access token const authResponse = await auth.getToken(auth.tokenRequest); // call the web API with the access token const users = await fetch.callApi(auth.apiConfig.uri, authResponse.accessToken); // display result console.log(users); } catch (error) { console.log(error); } break; default: console.log('Select a Graph operation first'); break; } }; main();
你刚刚创建的 index.js 文件引用了你接下来将创建的另外两个节点模块:
- auth.js - 使用 MSAL 节点从 Microsoft 标识平台获取访问令牌。
- fetch.js - 通过在对 API 的 HTTP 请求中包含访问令牌(在 auth.js 中获取)从 Microsoft Graph API 请求数据 。
在本教程结束时,项目的文件和目录结构应类似于:
NodeDaemonApp/
├── bin
│ ├── auth.js
│ ├── fetch.js
│ ├── index.js
├── package.json
└── .env
添加身份验证逻辑
在 bin 目录中,将以下代码添加到名为 auth.js 的新文件中 。 auth.js 中的代码从 Microsoft 标识平台获取访问令牌,以包含在 Microsoft Graph API 请求中。
const msal = require('@azure/msal-node');
/**
* Configuration object to be passed to MSAL instance on creation.
* For a full list of MSAL Node configuration parameters, visit:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/configuration.md
*/
const msalConfig = {
auth: {
clientId: process.env.CLIENT_ID,
authority: process.env.AAD_ENDPOINT + '/' + process.env.TENANT_ID,
clientSecret: process.env.CLIENT_SECRET,
}
};
/**
* With client credentials flows permissions need to be granted in the portal by a tenant administrator.
* The scope is always in the format '<resource>/.default'. For more, visit:
* /active-directory/develop/v2-oauth2-client-creds-grant-flow
*/
const tokenRequest = {
scopes: [process.env.GRAPH_ENDPOINT + '/.default'],
};
const apiConfig = {
uri: process.env.GRAPH_ENDPOINT + '/v1.0/users',
};
/**
* Initialize a confidential client application. For more info, visit:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/initialize-confidential-client-application.md
*/
const cca = new msal.ConfidentialClientApplication(msalConfig);
/**
* Acquires token with client credentials.
* @param {object} tokenRequest
*/
async function getToken(tokenRequest) {
return await cca.acquireTokenByClientCredential(tokenRequest);
}
module.exports = {
apiConfig: apiConfig,
tokenRequest: tokenRequest,
getToken: getToken
};
在上述代码片段中,我们首先创建一个 (msalConfig) 的配置对象,并将其传递给 MSAL ConfidentialClientApplication。 接下来,我们创建一个方法,用于通过客户端凭据获取令牌,并最终公开此模块以便通过 main.js 进行访问。 此模块中的配置参数是从环境文件中提取的,我们将在下一步中创建该文件。
添加应用注册详细信息
创建一个环境文件,以存储在获取令牌时将使用的应用注册详细信息。 为此,请在示例 (NodeDaemonApp) 的根文件夹中创建一个名为 .env 的文件,并添加以下代码:
# Credentials
TENANT_ID=Enter_the_Tenant_Id_Here
CLIENT_ID=Enter_the_Application_Id_Here
CLIENT_SECRET=Enter_the_Client_Secret_Here
# Endpoints
AAD_ENDPOINT=Enter_the_Cloud_Instance_Id_Here/
GRAPH_ENDPOINT=Enter_the_Graph_Endpoint_Here/
使用从 Azure 应用注册门户获取的值填写以下详细信息:
Enter_the_Tenant_Id_here
应是以下各项之一:- 如果应用程序支持“此组织目录中的帐户”,请将此值替换为“租户 ID”或“租户名称”。 例如,
contoso.microsoft.com
。 - 如果应用程序支持“任何组织目录中的帐户”,请将该值替换为“
organizations
”。
- 如果应用程序支持“此组织目录中的帐户”,请将此值替换为“租户 ID”或“租户名称”。 例如,
Enter_the_Application_Id_Here
:已注册应用程序的应用程序(客户端)ID。Enter_the_Cloud_Instance_Id_Here
:在其中注册应用程序的 Azure 云实例。- 对于国家/地区云(例如中国云),可以在国家/地区云中找到相应值。
Enter_the_Graph_Endpoint_Here
是应用程序应与之通信的 Microsoft Graph API 实例。- 对于国家/地区云部署中的终结点,请参阅 Microsoft Graph 文档中的国家/地区云部署。
添加方法来调用 Web API
在 bin 文件夹中创建另一个名为 fetch.js 的文件,并添加以下代码以对 Microsoft Graph API 进行 REST 调用 :
const axios = require('axios');
/**
* Calls the endpoint with authorization bearer token.
* @param {string} endpoint
* @param {string} accessToken
*/
async function callApi(endpoint, accessToken) {
const options = {
headers: {
Authorization: `Bearer ${accessToken}`
}
};
console.log('request made to web API at: ' + new Date().toString());
try {
const response = await axios.get(endpoint, options);
return response.data;
} catch (error) {
console.log(error)
return error;
}
};
module.exports = {
callApi: callApi
};
此处,使用 callApi
方法对需要令牌的受保护资源发出 HTTP GET
请求。 然后,该请求将内容返回给调用方。 此方法可在 HTTP 授权标头中添加获取的令牌。 此处的受保护资源是 Microsoft Graph API 用户终结点,该终结点显示在其中注册了此应用的租户中的用户。
测试应用
你已完成应用程序的创建,现在即可测试应用的功能。
从项目文件夹的根目录中运行以下命令,启动 Node.js 控制台守护程序应用:
node . --op getUsers
这会导致某些来自 Microsoft Graph API 的 JSON 响应,你应在控制台中看到用户对象的数组:
You have selected: getUsers
request made to web API at: Fri Jan 22 2021 09:31:52 GMT-0800 (Pacific Standard Time)
{
'@odata.context': 'https://microsoftgraph.chinacloudapi.cn/v1.0/$metadata#users',
value: [
{
displayName: 'Adele Vance'
givenName: 'Adele',
jobTitle: 'Retail Manager',
mail: 'AdeleV@msaltestingjs.partner.onmschina.cn',
mobilePhone: null,
officeLocation: '18/2111',
preferredLanguage: 'en-US',
surname: 'Vance',
userPrincipalName: 'AdeleV@msaltestingjs.partner.onmschina.cn',
id: '00aa00aa-bb11-cc22-dd33-44ee44ee44ee'
}
]
}
应用程序的工作原理
此应用程序使用 OAuth 2.0 客户端凭据授权。 这种授予通常用于必须在后台运行的服务器间交互,不需要立即与用户交互。 凭据授权流允许 Web 服务(机密客户端)在调用其他 Web 服务时使用它自己的凭据(而不是模拟用户)进行身份验证。 此身份验证模型支持的应用程序类型通常是守护程序或服务帐户 。
请求客户端凭据流时,其作用域是资源的名称后跟 /.default
。 这种表示法告知 Microsoft Entra ID 使用在应用程序注册过程中静态声明的应用程序级权限。 另外,这些 API 权限必须由租户管理员授予。
后续步骤
如果你想要更深入了解 Microsoft 标识平台上的 Node.js 守护程序应用程序开发,请参阅由多部分组成的方案系列: