你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
重要
自 2025 年 5 月 1 日起,Azure AD B2C 将不再可供新客户购买。 在我们的常见问题解答中了解详细信息。
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 响应,用户必须重新输入访问代码。
先决条件
如果没有租户,请创建链接到 Azure 订阅的 Azure AD B2C 租户。
必须在计算机上安装 Node.js 。
必须在计算机上安装 Visual Studio Code (VS Code)。
使用 Azure AD B2C 自定义策略完成验证用户输入中的步骤。 本文是创建和运行自己的自定义策略操作指南系列教程的一部分。
注释
本文是《在 Azure Active Directory B2C 中创建和运行自己的自定义策略操作指南系列教程》的一部分。 建议从第一篇文章开始本系列教程。
步骤 1 - 创建和部署 Node.js 应用
你需要部署一个应用,该应用充当外部应用。 然后,自定义策略对此应用进行 HTTP 调用。
步骤 1.1 - 创建 Node.js 应用
创建一个文件夹来托管节点应用程序,例如
access-code-app
。在终端中,将目录更改为 Node 应用文件夹,例如
cd access-code-app
,并运行npm init -y
。 此命令将为 Node.js 项目创建一个默认package.json
文件。在终端中,运行
npm install express body-parser
。 此命令安装 Express 框架和 正文分析程序 包。在项目中,创建
index.js
文件。在 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://learn.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 的源。 详细了解 如何返回验证错误消息。若要测试应用按预期工作,请使用以下步骤:
- 在终端中运行
node index.js
命令以启动应用服务器。 - 若要发出类似于此示例所示的 POST 请求,可以使用 HTTP 客户端(如 Microsoft PowerShell)。
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://learn.microsoft.com/en-us/azure/active-directory-b2c/string-transformations" }
- 在终端中运行
REST 服务可以返回 HTTP 4xx 状态代码,但 JSON 响应中的值 status
必须是 409
。
此时,您已准备好部署您的 Node.js 应用程序。
步骤 1.2 - 在 Azure 应用服务中部署 Node.js 应用
要支持自定义策略访问 Node.js 应用,它必须是可访问的,因此需要部署它。 在本文中,你将使用 Azure 应用服务部署应用,但使用替代的托管方法。
按照将 应用部署到 Azure 中的步骤将 Node.js 应用部署到 Azure。 对于应用 的名称 ,请使用描述性名称,例如 custompolicyapi
。 因此:
应用 URL 类似于
https://custompolicyapi.azurewebsites.net
.服务终结点看起来类似于
https://custompolicyapi.azurewebsites.net/validate-accesscode
.
可以使用 HTTP 客户端(如 Microsoft PowerShell)测试已部署的应用。 这一次,请使用 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)
、、Form
Header
或Url
QueryString
。 您使用Body
时(如本文中所示),会调用 POST HTTP 方法,您发送到 API 的数据在请求正文中被格式化为键值对。 了解如何调用 GET HTTP 谓词,并将数据作为查询字符串传递。AuthenticationType
指定 RESTful 声明提供程序执行的身份验证类型。 我们的 RESTful 声明提供程序将调用不受保护的终结点,因此我们将AuthenticationType
设置为“无”。 如果将身份验证类型设置为Bearer
,则需要添加 CryptographicKeys 元素,该元素指定访问令牌的存储。 详细了解 RESTful 声明提供程序支持的身份验证类型。中的
InputClaim
属性指定如何在 API 中接收数据。
步骤 2.2 - 更新验证技术配置文件
在使用 Azure AD B2C 自定义策略在用户旅程中创建分支中,你使用声明转换验证了 accessCode。 在本文中,将通过对外部服务进行 HTTP 调用来验证 accessCode 。 因此,需要更新自定义策略以反映新方法。
找到 AccessCodeInputCollector 技术配置文件,并将 ValidationTechnicalProfile 元素的 ReferenceId 更新为 ValidateAccessCodeViaHttp:
从:
<ValidationTechnicalProfile ReferenceId="CheckAccessCodeViaClaimsTransformationChecker"/>
到:
<ValidationTechnicalProfile ReferenceId="ValidateAccessCodeViaHttp"/>
此时,不再需要Id
CheckAccessCodeViaClaimsTransformationChecker的技术简介,并且可以删除。
步骤 3 - 上传自定义策略文件
确保 Node.js 应用正在运行,然后按照 “上传自定义策略文件” 中的步骤上传策略文件。 如果要上传与门户中已有的文件同名的文件,请确保选择“覆盖自定义策略(如果已存在)”。
步骤 4 - 测试自定义策略
按照 测试自定义策略 中的步骤测试自定义策略:
- 对于帐户类型,请选择“个人帐户”
- 根据需要输入其余详细信息,然后选择“ 继续”。 你会看到一个新屏幕。
- 对于 访问代码,请输入 88888,然后选择“ 继续”。 策略完成执行后,会重定向到
https://jwt.ms
并看到解码的 JWT。 如果重复此过程,并输入除 88888 以外的其他访问代码,则会看到错误,输入的访问代码不正确。请重试。
步骤 5 - 启用调试模式
在开发中,你可能希望看到 API 发送的详细错误,例如 developerMessage 和 moreInfo。 在这种情况下,需要在 RESTful 技术提供程序中启用调试模式。
找到 ValidateAccessCodeViaHttp 技术提供程序,并在技术提供程序的
metadata
项中添加以下项:<Item Key="DebugMode">true</Item>
保存更改并 上传策略文件。
测试自定义策略。 请确保为“访问代码”使用错误的输入。 你会看到类似于以下屏幕截图中显示的错误:
处理复杂的 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":"aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
"firstName":"John",
"lastName":"Smith",
"accessCode":"88888",
"role":{
"name":"Administrator",
"id": 1
}
}
}
然后,更新 RESTful 技术提供程序的 Metadata、 InputClaimsTransformations 和 InputClaims ,如下所示:
<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 正文。
相关内容
接下来,学习: