使用 Azure Active Directory B2C 自訂原則呼叫 REST API

Azure Active Directory B2C (Azure AD B2C) 自訂原則可讓您與在 Azure AD B2C 外部實作的應用程式邏輯進行互動。 若要這樣做,您要對端點發出 HTTP 呼叫。 針對此目的,Azure AD B2C 自訂原則提供 RESTful 技術設定檔。 藉由使用這項功能,您可以實作 Azure AD B2C 自訂原則內無法使用的功能。

在本文中,您將學會如何:

  • 建立並部署範例 Node.js 應用程式,做為 RESTful 服務之用。

  • 使用 RESTful 技術設定檔對 Node.js RESTful 服務發出 HTTP 呼叫。

  • 處理或回報 RESTful 服務傳回至自訂原則的錯誤。

案例概觀

使用 Azure AD B2C 自訂原則建立使用者旅程圖中的分支中,選取 [個人帳戶] 的使用者必須提供有效的邀請存取碼才能繼續。 我們使用靜態存取碼,但真實世界的應用程式作法不是這樣。 如果發出存取碼的服務是自訂原則外部的服務,您必須呼叫該服務,傳遞使用者輸入的存取碼以進行驗證。 如果存取碼有效,服務傳回 HTTP 200 OK 回應,然後 Azure AD B2C 發出 JWT 權杖。 否則,服務傳回 HTTP 4xx 回應,而使用者必須重新輸入存取碼。

A flowchart of calling a R E S T A P I.

必要條件

注意

此文是在 Azure Active Directory B2C 中建立並執行您自己的自訂原則之使用方法指南系列的一部分。 建議您從第一篇文章開始參閱這個系列。

步驟 1 - 建立並部署 Node.js 應用程式

您必須部署一個應用程式做為外部應用程式。 您的自訂原則接著會對此應用程式發出 HTTP 呼叫。

步驟 1.1 - 建立 Node.js 應用程式

  1. 建立資料夾以裝載您的 Node 應用程式,例如 access-code-app

  2. 在您的終端機中,將目錄變更為您的 Node 應用程式資料夾 (例如 cd access-code-app),然後執行 npm init -y。 此命令會建立 Node.js 專案的預設 package.json 檔案。

  3. 在終端中執行 npm install express body-parser。 此命令安裝 Express 架構和 body-parser (本文剖析器) 套件。

  4. 在您的專案中,建立 index.js 檔案。

  5. 在 VS Code 中,開啟 index.js 檔案,然後新增下列程式碼:

        const express = require('express');
        let bodyParser = require('body-parser')
        //Create an express instance
        const app = express();
    
        app.use( bodyParser.json() );       // to support JSON-encoded bodies
        app.use(bodyParser.urlencoded({     // to support URL-encoded bodies
          extended: true
        }));
    
    
        app.post('/validate-accesscode', (req, res) => {
            let accessCode = '88888';
            if(accessCode == req.body.accessCode){
                res.status(200).send();
            }else{
                let errorResponse = {
                    "version" :"1.0",
                    "status" : 409,
                    "code" : "errorCode",
                    "requestId": "requestId",
                    "userMessage" : "The access code you entered is incorrect. Please try again.",
                    "developerMessage" : `The provided code ${req.body.accessCode} does not match the expected code for user.`,
                    "moreInfo" :"https://docs.microsoft.com/en-us/azure/active-directory-b2c/string-transformations"
                };
                res.status(409).send(errorResponse);                
            }
        });
    
        app.listen(80, () => {
            console.log(`Access code service listening on port !` + 80);
        });
    

    您可以觀察到當使用者提交錯誤存取碼時,您可以直接從 REST API 傳回錯誤。 自訂原則可讓您傳回 HTTP 4xx 錯誤訊息,例如 400 (不正確的要求) 或 409 (衝突) 回應狀態碼,其回應 JSON 本文的格式如 errorResponse 變數所示。 您可以從資料庫讀取應用程式中的 accessCode 來源。 深入了解傳回驗證錯誤訊息

  6. 若要測試應用程式是否如預期般運作,請利用下列步驟:

    1. 在您的終端機中,執行 node index.js 命令以啟動您的應用程式伺服器。
    2. 若要發出類似此範例中所示的 POST 要求,您可以使用 HTTP 用戶端,例如 Microsoft PowerShellPostman
        POST http://localhost/validate-accesscode HTTP/1.1
        Host: localhost
        Content-Type: application/x-www-form-urlencoded
    
        accessCode=user-code-code
    

    user-code-code 取代為使用者輸入的存取碼,例如 54321。 如果您使用 PowerShell,請執行下列指令碼。

        $accessCode="54321"
        $endpoint="http://localhost/validate-accesscode"
        $body=$accessCode
        $response=Invoke-RestMethod -Method Post -Uri $endpoint -Body $body
        echo $response
    

    如果您使用不正確的存取碼,回應看起來會類似下列 JSON 程式碼片段:

        {
            "version": "1.0",
            "status": 409,
            "code": "errorCode",
            "requestId": "requestId",
            "userMessage": "The access code you entered is incorrect. Please try again.",
            "developerMessage": "The provided code 54321 does not match the expected code for user.",
            "moreInfo": "https://docs.microsoft.com/en-us/azure/active-directory-b2c/string-transformations"
        }
    

REST 服務可以傳回 HTTP 4xx 狀態碼,但是 JSON 回應中的 status 值必須是 409

至此,您已準備好部署 Node.js 應用程式。

步驟 1.2 - 在 Azure App Service 中部署 Node.js 應用程式

若要讓自訂原則觸達您的 Node.js 應用程式,應用程式必須在觸達範圍內,因此,您必須部署應用程式。 在本文中,您使用 Azure App Service 部署應用程式,但使用替代的裝載方法。

請遵循將應用程式部署至 Azure 中的步驟,將 Node.js 應用程式部署至 Azure。 針對應用程式的名稱,請使用描述性名稱,例如 custompolicyapi。 因此:

  • 應用程式 URL 看起來會類似 https://custompolicyapi.azurewebsites.net

  • 服務端點看起來會類似 https://custompolicyapi.azurewebsites.net/validate-accesscode

您可以使用 Microsoft PowerShellPostman 等 HTTP 用戶端測試已部署的應用程式。 這次,請使用 https://custompolicyapi.azurewebsites.net/validate-accesscode URL 做為端點。

步驟 2 - 呼叫 REST API

現在您的應用程式正在執行中,您必須從自訂原則發出 HTTP 呼叫。 Azure AD B2C 自訂原則提供 RESTful 技術設定檔,您可以用來呼叫外部服務。

步驟 2.1 - 定義 RESTful 技術設定檔

在您的 ContosoCustomPolicy.XML 檔案中找到 ClaimsProviders 區段,然後使用下列程式碼定義新的 RESTful 技術設定檔:

    <!--<ClaimsProviders>-->
        <ClaimsProvider>
            <DisplayName>HTTP Request Technical Profiles</DisplayName>
            <TechnicalProfiles>
                <TechnicalProfile Id="ValidateAccessCodeViaHttp">
                    <DisplayName>Check that the user has entered a valid access code by using Claims Transformations</DisplayName>
                    <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
                    <Metadata>
                        <Item Key="ServiceUrl">https://custompolicyapi.azurewebsites.net/validate-accesscode</Item>
                        <Item Key="SendClaimsIn">Body</Item>
                        <Item Key="AuthenticationType">None</Item>
                        <Item Key="AllowInsecureAuthInProduction">true</Item>
                    </Metadata>
                    <InputClaims>
                        <InputClaim ClaimTypeReferenceId="accessCode" PartnerClaimType="accessCode" />
                    </InputClaims>
                </TechnicalProfile>
            </TechnicalProfiles>
        </ClaimsProvider>
    <!--</ClaimsProviders>-->

您可以從通訊協定中觀察到,我們將技術設定檔設定為使用 RestfulProvider。 您也可以在中繼資料區段中觀察到下列資訊:

  • ServiceUrl 代表 API 端點。 其值為 https://custompolicyapi.azurewebsites.net/validate-accesscode。 如果您使用替代方法部署 Node.js 應用程式,請務必更新端點值。

  • SendClaimsIn 指定輸入宣告如何傳送至 RESTful 宣告提供者。 可能的值有:Body (default)FormHeaderUrlQueryString。 例如在此文中,若您使用 Body,您叫用 POST HTTP 指令動詞,您的資料會以要求本文中的索引鍵值組格式傳送至 API。 了解如何叫用 GET HTTP 指令動詞,然後以查詢字串格式傳遞資料

  • AuthenticationType 指定 RESTful 宣告提供者執行的驗證類型。 我們的 RESTful 宣告提供者會呼叫未受保護的端點,因此我們將 AuthenticationType 設定為 None。 如果您將驗證類型設定為 Bearer,您必須新增 CryptographicKeys 元素,此元素指定存取權杖的儲存體。 深入了解 RESTful 宣告提供者支援的驗證類型

  • InputClaim 中的 PartnerClaimType 屬性指定如何在 API 中接收您的資料。

步驟 2.2 - 更新驗證技術設定檔

使用 Azure AD B2C 自訂原則建立使用者旅程圖中的分支中,您已使用宣告轉換驗證 accessCode。 在本文中,您對外部服務發出 HTTP 呼叫以驗證 accessCode。 因此,您必須更新自訂原則來反映新方法。

找到 AccessCodeInputCollector 技術設定檔,將 ValidationTechnicalProfile 元素的 ReferenceId 更新為 ValidateAccessCodeViaHttp

從:

    <ValidationTechnicalProfile ReferenceId="CheckAccessCodeViaClaimsTransformationChecker"/>

變更為:

    <ValidationTechnicalProfile ReferenceId="ValidateAccessCodeViaHttp"/>

至此,具有 IdCheckAccessCodeViaClaimsTransformationChecker 的技術設定檔已非必要,可加以移除。

步驟 3 - 上傳自訂原則檔案

請確定您的 Node.js 應用程式正在執行中,然後遵循上傳自訂原則檔案中的步驟,上傳您的原則檔案。 如果您要上傳的檔案與入口網站中的檔案名稱相同,請確定選取 [覆寫自訂原則 (如果已存在)]

步驟 4 - 測試自訂原則

請遵循測試自訂原則中的步驟,測試您的自訂原則:

  1. 在 [帳戶類型] 選取 [個人帳戶]
  2. 視需要輸入其餘的詳細資料,然後選取 [繼續]。 您會看到新畫面。
  3. 在 [存取碼] 輸入 88888,然後選取 [繼續]。 原則完成執行之後,系統會將您重新導向至 https://jwt.ms,您會看到已解碼的 JWT 權杖。 如果您重複此程序,輸入 88888 以外的不同 [存取碼],您會看到錯誤:您輸入的存取碼不正確。請再試一次。

步驟 5 - 啟用偵錯模式

在開發過程中,您可能想要查看 API 傳送的詳細錯誤,例如 developerMessagemoreInfo。 在此情況下,您必須在 RESTful 技術提供者中啟用偵錯模式。

  1. 找到 ValidateAccessCodeViaHttp 技術提供者,在技術提供者的 metadata 中新增下列項目:

        <Item Key="DebugMode">true</Item>
    
  2. 儲存變更,然後上傳您的原則檔案

  3. 測試自訂原則。 請確定輸入錯誤的存取碼。 您會看到類似此螢幕擷取畫面所顯示的錯誤:

    A screenshot error when you enable debug mode.

處理複雜的要求 JSON 承載

如果您呼叫的 REST API 要求您傳送複雜的 JSON 承載,您可以使用 GenerateJson JSON 宣告轉換建立承載。 產生承載之後,您就可以使用 ClaimUsedForRequestPayload 中繼資料選項,用於包含 JSON 承載的宣告名稱。

例如,使用下列宣告轉換以產生 JSON 承載:

    <ClaimsTransformation Id="GenerateRequestBodyClaimsTransformation" TransformationMethod="GenerateJson">
        <InputClaims>
            <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="customerEntity.email" />
            <InputClaim ClaimTypeReferenceId="objectId" TransformationClaimType="customerEntity.userObjectId" />
            <InputClaim ClaimTypeReferenceId="givenName" TransformationClaimType="customerEntity.firstName" />
            <InputClaim ClaimTypeReferenceId="surname" TransformationClaimType="customerEntity.lastName" />
            <InputClaim ClaimTypeReferenceId="accessCode" TransformationClaimType="customerEntity.accessCode" />
        </InputClaims>
        <InputParameters>
            <InputParameter Id="customerEntity.role.name" DataType="string" Value="Administrator" />
            <InputParameter Id="customerEntity.role.id" DataType="long" Value="1" />
        </InputParameters>
        <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="requestBodyPayload" TransformationClaimType="outputClaim" />
        </OutputClaims>
    </ClaimsTransformation>

ClaimsTransformation 產生下列 JSON 物件:

{
   "customerEntity":{
      "email":"john.s@contoso.com",
      "userObjectId":"01234567-89ab-cdef-0123-456789abcdef",
      "firstName":"John",
      "lastName":"Smith",
      "accessCode":"88888",
      "role":{
         "name":"Administrator",
         "id": 1
      }
   }
}

然後,更新 RESTful 技術提供者的 MetadataInputClaimsTransformationsInputClaims,如下所示:

    <Metadata>
        <Item Key="ClaimUsedForRequestPayload">requestBodyPayload</Item>
        <!--Other Metadata items -->
    </Metadata>
    
    <!--Execute your InputClaimsTransformations to generate your request Payload-->
    <InputClaimsTransformations>
        <InputClaimsTransformation ReferenceId="GenerateRequestBodyClaimsTransformation" />
    </InputClaimsTransformations>
    
    <InputClaims>
        <InputClaim ClaimTypeReferenceId="requestBodyPayload" />
    </InputClaims>

從 REST API 接收資料

如果您的 REST API 傳回資料,您想要將資料包含在原則中做為宣告,您可以在 RESTful 技術設定檔的 OutputClaims 元素中指定宣告來接收資料。 如果原則中定義的宣告名稱與 REST API 中定義的名稱不同,您必須使用 PartnerClaimType 屬性來對應這些名稱。

請利用接收資料中的步驟,深入了解如何將資料格式化為自訂原則預期的資料格式,如何處理 Null 值,以及如何剖析 REST API 的巢狀 JSON 本文。

下一步

接下來,請了解: