教學課程:從 Node.js 精靈應用程式呼叫 Web API
本教學課程是系列的最後一部分,示範如何使用 Open Authorization (OAuth) 2.0 用戶端認證授與流程來準備 Node.js 精靈用戶端應用程式,然後將其設定為取得用於呼叫 Web API 的存取權杖。 在此系列的第 1 部分中,您已在 Microsoft Entra 系統管理中心內註冊 Web API 和精靈應用程式,並授與權限。 這個最後一個步驟示範如何使用適用於 Node 的 Microsoft 驗證程式庫 (MSAL) 來建置 Node.js 應用程式,以簡化將授權新增至您的應用程式。
本教學課程內容;
- 在 Visual Studio Code 中建立 Node.js 應用程式,然後安裝相依性。
- 讓 Node.js 應用程式取得用於呼叫 Web API 的存取權杖。
必要條件
- 教學課程:準備外部租用戶以授權 Node.js 精靈應用程式。
- 正在執行並準備好接受要求的受保護 Web API。 如果您尚未建立,請參閱建立受保護的 Web API 教學課程。 請確定此 Web API 使用您在準備租用戶教學課程中所建立的應用程式註冊詳細資料。 請確定您的 Web API 透過 HTTPS 來公開下列端點:
GET /api/todolist
以取得所有待辦事項。POST /api/todolist
以新增 TODO。
- Node.js。
- 雖然可以使用任何支援 React 應用程式的整合式開發環境 (IDE),但本教學課程使用 Visual Studio Code。
- 您在準備租用戶教學課程中所建立 Node.js 精靈應用程式和 Web API 的註冊詳細資料。
建立 Node.js 精靈專案
建立資料夾以裝載您的 Node 精靈應用程式 (例如 ciam-call-api-node-daemon
):
在終端機中,將目錄變更為您的 Node 精靈應用程式資料夾 (例如
cd ciam-call-api-node-daemon
),然後執行npm init -y
。 此命令會為 Node.js 專案建立預設 package.json 檔案。 此命令會建立 Node.js 專案的預設package.json
檔案。建立其他資料夾和檔案,以達成下列專案結構:
ciam-call-api-node-daemon/ ├── auth.js └── authConfig.js └── fetch.js └── index.js └── package.json
安裝應用程式相依性
在終端機中,執行下列命令以安裝 axios
、yargs
和 @azure/msal-node
套件:
npm install axios yargs @azure/msal-node
建立 MSAL 設定物件
在您的程式碼編輯器中,開啟 authConfig.js 檔案,然後新增下列程式碼:
require('dotenv').config();
/**
* 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 || 'Enter_the_Application_Id_Here', // 'Application (client) ID' of app registration in Azure portal - this value is a GUID
authority: process.env.AUTHORITY || 'https://Enter_the_Tenant_Subdomain_Here.ciamlogin.com/', // Replace "Enter_the_Tenant_Subdomain_Here" with your tenant subdomain
clientSecret: process.env.CLIENT_SECRET || 'Enter_the_Client_Secret_Here', // Client secret generated from the app
},
system: {
loggerOptions: {
loggerCallback(loglevel, message, containsPii) {
console.log(message);
},
piiLoggingEnabled: false,
logLevel: 'Info',
},
},
};
const protectedResources = {
apiToDoList: {
endpoint: process.env.API_ENDPOINT || 'https://localhost:44351/api/todolist',
scopes: [process.env.SCOPES || 'api://Enter_the_Web_Api_Application_Id_Here'],
},
};
module.exports = {
msalConfig,
protectedResources,
};
msalConfig
物件包含一組設定選項,可用來自訂授權流程的行為。
在 authConfig.js 檔案中,取代:
Enter_the_Application_Id_Here
為您稍早所註冊用戶端精靈應用程式的應用程式 (用戶端) 識別碼。Enter_the_Tenant_Subdomain_Here
,並將其取代為目錄 (租用戶) 子網域。 例如,若租用戶主要網域是contoso.onmicrosoft.com
,請使用contoso
。 如果您沒有租用戶名稱,請了解如何讀取租用戶詳細資料。Enter_the_Client_Secret_Here
為您稍早複製的用戶端精靈應用程式祕密值。Enter_the_Web_Api_Application_Id_Here
為您稍早所複製 Web API 應用程式的應用程式 (用戶端) 識別碼。
請注意,protectedResources
變數中的 scopes
屬性是您稍早所註冊 Web API 的資源識別碼 (應用程式識別碼 URI)。 完整的範圍 URI 看起來類似 api://Enter_the_Web_Api_Application_Id_Here/.default
。
取得存取權杖
在您的程式碼編輯器中,開啟 auth.js 檔案,然後新增下列程式碼:
const msal = require('@azure/msal-node');
const { msalConfig, protectedResources } = require('./authConfig');
/**
* With client credentials flows permissions need to be granted in the portal by a tenant administrator.
* The scope is always in the format '<resource-appId-uri>/.default'. For more, visit:
* https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
*/
const tokenRequest = {
scopes: [`${protectedResources.apiToDoList.scopes}/.default`],
};
const apiConfig = {
uri: protectedResources.apiToDoList.endpoint,
};
/**
* 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,
};
在程式碼中:
準備
tokenRequest
和apiConfig
物件。tokenRequest
包含您要求存取權杖的範圍。 範圍看起來像api://Enter_the_Web_Api_Application_Id_Here/.default
。apiConfig
物件包含 Web API 的端點。 深入了解 OAuth 2.0 用戶端認證流程。您可以將
msalConfig
物件傳遞至 ConfidentialClientApplication 類別的建構函式,以建立機密用戶端執行個體。const cca = new msal.ConfidentialClientApplication(msalConfig);
您接著會使用 acquireTokenByClientCredential 函數來取得存取權杖。 您會在
getToken
函數中實作此邏輯:cca.acquireTokenByClientCredential(tokenRequest);
取得存取權杖之後,您可以繼續呼叫 API。
呼叫 API
在您的程式碼編輯器中,開啟 fetch.js 檔案,然後新增下列程式碼:
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
};
在此程式碼中,您會在要求 Authorization
標頭中以持有人權杖形式傳遞存取權杖來呼叫 Web API:
Authorization: `Bearer ${accessToken}`
您會使用稍早在取得存取權杖中取得的存取權杖。
Web API 在收到要求之後,會對其進行評估,然後判斷其是否為應用程式要求。 如果存取權杖有效,則 Web API 會傳回所要求的資料。 否則,API 會傳回 401 Unauthorized
HTTP 錯誤。
完成精靈應用程式
在您的程式碼編輯器中,開啟 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 'getToDos':
try {
const authResponse = await auth.getToken(auth.tokenRequest);
const todos = await fetch.callApi(auth.apiConfig.uri, authResponse.accessToken);
} catch (error) {
console.log(error);
}
break;
default:
console.log('Select an operation first');
break;
}
};
main();
此程式碼是您應用程式的進入點。 您使用可剖析程式庫的 yargs JavaScript 命令列引數,讓 Node.js 應用程式以互動方式擷取存取權杖,然後呼叫 API。 您使用稍早定義的 getToken
和 callApi
函數:
const authResponse = await auth.getToken(auth.tokenRequest);
const todos = await fetch.callApi(auth.apiConfig.uri, authResponse.accessToken);
執行並測試精靈應用程式和 API
此時,您已準備好測試用戶端精靈應用程式和 Web API:
使用您在保護 ASP.NET Web API 教學課程中所學到的步驟來啟動 Web API。 您的 Web API 現在已準備好提供用戶端要求。 如果您未在 authConfig.js 檔案中所指定的連接埠
44351
上執行 Web API,請務必更新 authConfig.js 檔案,以使用正確的 Web API 連接埠號碼。在您的終端機中,確定您位於包含精靈 Node.js 應用程式的專案資料夾中 (例如
ciam-call-api-node-daemon
),然後執行下列命令:node . --op getToDos
如果您的精靈應用程式和 Web API 成功執行,則您應該會在主控台視窗中找到 Web API 端點 todos
變數所傳回的資料,與下列 JSON 陣列類似:
{
id: 1,
owner: '3e8....-db63-43a2-a767-5d7db...',
description: 'Pick up grocery'
},
{
id: 2,
owner: 'c3cc....-c4ec-4531-a197-cb919ed.....',
description: 'Finish invoice report'
},
{
id: 3,
owner: 'a35e....-3b8a-4632-8c4f-ffb840d.....',
description: 'Water plants'
}