在 Azure Active Directory B2C 自定义策略中定义 RESTful 技术配置文件

重要

自 2025 年 5 月 1 日起,Azure AD B2C 将不再可供新客户购买。 在我们的常见问题解答中了解详细信息。

注释

在 Azure Active Directory B2C 中,自定义策略 主要用于解决复杂场景。 对于大多数场景,我们建议您使用内置的用户流。 如果未这样做,请通过 Active Directory B2C 中的自定义策略入门来了解自定义策略初学者包。

Azure Active Directory B2C (Azure AD B2C) 支持集成自己的 RESTful 服务。 Azure AD B2C 将数据发送到输入声明集合中的 RESTful 服务,并在输出声明集合中接收数据。

协议

“Protocol”元素的“Name”属性必须设置为 。 处理程序属性必须包含 Azure AD B2C 使用的协议处理程序程序集的完全限定名称: Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

以下示例显示了 RESTful 技术配置文件:

<TechnicalProfile Id="REST-UserMembershipValidator">
  <DisplayName>Validate user input data and return loyaltyNumber claim</DisplayName>
  <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  ...

输入声明

InputClaims 元素包含要发送到 REST API 的声明列表。 还可以将声明的名称映射到 REST API 中定义的名称。 以下示例显示了策略与 REST API 之间的映射。 givenName 声明作为 firstName 发送到 REST API,而姓氏作为 lastName 发送。 电子邮件声明按原样设置。

<InputClaims>
  <InputClaim ClaimTypeReferenceId="email" />
  <InputClaim ClaimTypeReferenceId="givenName" PartnerClaimType="firstName" />
  <InputClaim ClaimTypeReferenceId="surname" PartnerClaimType="lastName" />
</InputClaims>

InputClaimsTransformations 元素可能包含 InputClaimsTransformation 元素的集合,这些元素用于在发送到 REST API 之前修改输入声明或生成新元素。

发送 JSON 有效负载

REST API 技术配置文件允许将复杂的 JSON 有效负载发送到终结点。

发送复杂的 JSON 有效负载:

  1. 使用 GenerateJson 声明转换生成 JSON 有效负载。
  2. 在 REST API 技术配置文件中:
    1. 添加具有对声明转换的引用的 GenerateJson 输入声明转换。
    2. 将 SendClaimsIn 元数据选项设置为 body
    3. 将 ClaimUsedForRequestPayload 元数据选项设置为包含 JSON 有效负载的声明的名称。
    4. 在输入声明中,添加对包含 JSON 有效负载的输入声明的引用。

以下示例 TechnicalProfile 使用第三方电子邮件服务(在本例中为 SendGrid)发送验证电子邮件。

<TechnicalProfile Id="SendGrid">
  <DisplayName>Use SendGrid's email API to send the code to the user</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://api.sendgrid.com/v3/mail/send</Item>
    <Item Key="AuthenticationType">Bearer</Item>
    <Item Key="SendClaimsIn">Body</Item>
    <Item Key="ClaimUsedForRequestPayload">sendGridReqBody</Item>
    <Item Key="DefaultUserMessageIfRequestFailed">Cannot process your request right now, please try again later.</Item>
  </Metadata>
  <CryptographicKeys>
    <Key Id="BearerAuthenticationToken" StorageReferenceId="B2C_1A_SendGridApiKey" />
  </CryptographicKeys>
  <InputClaimsTransformations>
    <InputClaimsTransformation ReferenceId="GenerateSendGridRequestBody" />
  </InputClaimsTransformations>
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="sendGridReqBody" />
  </InputClaims>
</TechnicalProfile>

输出声明

OutputClaims 元素包含 REST API 返回的声明列表。 可能需要将策略中定义的声明的名称映射到 REST API 中定义的名称。 还可以包含 REST API 不返回的声明,只要设置 DefaultValue 属性。

OutputClaimsTransformations 元素可能包含用于修改输出声明或生成新输出声明的 OutputClaimsTransformation 元素集合。

以下示例演示 REST API 返回的声明:

  • 映射到 loyaltyNumber 声明名称的 MembershipId 声明。

技术配置文件还返回标识提供者未返回的声明:

  • 将默认值设置为的 true 声明。
<OutputClaims>
  <OutputClaim ClaimTypeReferenceId="loyaltyNumber" PartnerClaimType="MembershipId" />
  <OutputClaim ClaimTypeReferenceId="loyaltyNumberIsNew" DefaultValue="true" />
</OutputClaims>

元数据

特征 必选 DESCRIPTION
ServiceUrl 是的 REST API 终结点的 URL。
身份验证类型 是的 RESTful 声明提供程序执行的身份验证类型。 可能的值:None、、BasicBearer、ClientCertificate或ApiKeyHeader。
  • 该值 None 指示 REST API 是匿名的。
  • 该值 Basic 指示 REST API 使用 HTTP 基本身份验证进行保护。 只有已验证的用户(包括 Azure AD B2C)才能访问 API。
  • 值 ClientCertificate 指示 REST API 使用客户端证书身份验证限制访问。 只有具有相应证书的服务(例如 Azure AD B2C)才能访问 API。
  • 该值 Bearer 指示 REST API 使用客户端 OAuth2 持有者令牌限制访问。
  • 该值 ApiKeyHeader 指示 REST API 使用 API 密钥 HTTP 标头(如 x-functions-key)进行保护。
AllowInsecureAuthInProduction 否 指示是否可以AuthenticationType在生产环境中将它设置为 none (DeploymentModeTrustFrameworkPolicy 设置为Production或未指定)。 可能的值:true 或 false(默认值)。
SendClaimsIn 否 指定如何将输入声明发送到 RESTful 声明提供程序。 可能的值: Body (默认值)、Form或 HeaderUrlQueryString。
该值 Body 是以 JSON 格式的请求正文发送的输入声明。
该值 Form 是在请求正文中以“&”分隔的键值格式发送的输入声明。
该值 Header 是在请求标头中发送的输入声明。
该值 Url 是在 URL 中发送的输入声明,例如 https://api.example.com/{claim1}/{claim2}?{claim3}={claim4}。 URL 的主机名部分不能包含声明。
该值 QueryString 是在请求查询字符串中发送的输入声明。
每个谓词调用的 HTTP 谓词如下所示:
  • Body:发布
  • Form:发布
  • Header:获取
  • Url:获取
  • QueryString:获取
ClaimsFormat 否 当前未使用,可以忽略。
ClaimUsedForRequestPayload 否 包含要发送到 REST API 的有效负载的字符串声明的名称。
DebugMode 否 在调试模式下运行技术配置文件。 可能的值:true 或 false(默认值)。 在调试模式下,REST API 可以返回更多信息。 请参阅 “返回错误消息 ”部分。
IncludeClaimResolvingInClaimsHandling 否 对于输入和输出声明,指定声明解析是否包含在技术配置文件中。 可能的值:true 或 false(默认值)。 若要使用技术配置文件中的声明解析程序,请将此项设为 true。
ResolveJsonPathsInJsonTokens 否 指示技术配置文件是否解析 JSON 路径。 可能的值:true 或 false(默认值)。 使用此元数据从嵌套 JSON 元素读取数据。 在 OutputClaim 中 PartnerClaimType ,设置要输出的 JSON 路径元素。 例如:firstName.localized 或 data[0].to[0].email。
UseClaimAsBearerToken 否 包含持有者令牌的声明的名称。

错误处理

以下元数据可用于配置 REST API 失败时显示的错误消息。 可以将错误消息本地化。

特征 必选 DESCRIPTION
DefaultUserMessageIfRequestFailed 否 所有 REST API 异常的默认自定义错误消息。
UserMessageIfCircuitOpen 否 无法访问 REST API 时出现错误消息。 如果未指定,则返回 DefaultUserMessageIfRequestFailed。
UserMessageIfDnsResolutionFailed 否 DNS 解析异常的错误消息。 如果未指定,则返回 DefaultUserMessageIfRequestFailed。
UserMessageIfRequestTimeout 否 连接超时时出现错误消息。如果未指定,则返回 DefaultUserMessageIfRequestFailed。

加密密钥

如果身份验证类型设置为 None,则不使用 CryptographicKeys 元素。

<TechnicalProfile Id="REST-API-SignUp">
  <DisplayName>Validate user's input data and return loyaltyNumber claim</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://your-app-name.chinacloudsites.cn/api/identity/signup</Item>
    <Item Key="AuthenticationType">None</Item>
    <Item Key="SendClaimsIn">Body</Item>
  </Metadata>
</TechnicalProfile>

如果身份验证类型设置为 Basic, 则 CryptographicKeys 元素包含以下属性:

特征 必选 DESCRIPTION
BasicAuthenticationUsername 是的 用于进行身份验证的用户名。
BasicAuthenticationPassword 是的 用于进行身份验证的密码。

以下示例显示了具有基本身份验证的技术配置文件:

<TechnicalProfile Id="REST-API-SignUp">
  <DisplayName>Validate user's input data and return loyaltyNumber claim</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://your-app-name.chinacloudsites.cn/api/identity/signup</Item>
    <Item Key="AuthenticationType">Basic</Item>
    <Item Key="SendClaimsIn">Body</Item>
  </Metadata>
  <CryptographicKeys>
    <Key Id="BasicAuthenticationUsername" StorageReferenceId="B2C_1A_B2cRestClientId" />
    <Key Id="BasicAuthenticationPassword" StorageReferenceId="B2C_1A_B2cRestClientSecret" />
  </CryptographicKeys>
</TechnicalProfile>

如果身份验证类型设置为 ClientCertificate, 则 CryptographicKeys 元素包含以下属性:

特征 必选 DESCRIPTION
客户端证书 是的 用于进行身份验证的 X509 证书(RSA 密钥集)。
<TechnicalProfile Id="REST-API-SignUp">
  <DisplayName>Validate user's input data and return loyaltyNumber claim</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://your-app-name.chinacloudsites.cn/api/identity/signup</Item>
    <Item Key="AuthenticationType">ClientCertificate</Item>
    <Item Key="SendClaimsIn">Body</Item>
  </Metadata>
  <CryptographicKeys>
    <Key Id="ClientCertificate" StorageReferenceId="B2C_1A_B2cRestClientCertificate" />
  </CryptographicKeys>
</TechnicalProfile>

如果身份验证类型设置为 Bearer, 则 CryptographicKeys 元素包含以下属性:

特征 必选 DESCRIPTION
BearerAuthenticationToken 否 OAuth 2.0 持有者令牌。
<TechnicalProfile Id="REST-API-SignUp">
  <DisplayName>Validate user's input data and return loyaltyNumber claim</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://your-app-name.chinacloudsites.cn/api/identity/signup</Item>
    <Item Key="AuthenticationType">Bearer</Item>
    <Item Key="SendClaimsIn">Body</Item>
  </Metadata>
  <CryptographicKeys>
    <Key Id="BearerAuthenticationToken" StorageReferenceId="B2C_1A_B2cRestClientAccessToken" />
  </CryptographicKeys>
</TechnicalProfile>

如果身份验证类型设置为 ApiKeyHeader, 则 CryptographicKeys 元素包含以下属性:

特征 必选 DESCRIPTION
HTTP 标头的名称,例如 x-functions-key, 或 x-api-key。 是的 用于进行身份验证的密钥。

注释

目前,Azure AD B2C 仅支持一个 HTTP 标头进行身份验证。 如果 RESTful 调用需要多个标头(例如客户端 ID 和客户端机密值),则需要以某种方式代理请求。

<TechnicalProfile Id="REST-API-SignUp">
  <DisplayName>Validate user's input data and return loyaltyNumber claim</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://your-app-name.chinacloudsites.cn/api/identity/signup</Item>
    <Item Key="AuthenticationType">ApiKeyHeader</Item>
    <Item Key="SendClaimsIn">Body</Item>
  </Metadata>
  <CryptographicKeys>
    <Key Id="x-functions-key" StorageReferenceId="B2C_1A_RestApiKey" />
  </CryptographicKeys>
</TechnicalProfile>

返回验证错误消息

REST API 可能需要返回错误消息,例如“在 CRM 系统中找不到用户”。 如果发生错误,REST API 应返回 HTTP 4xx 错误消息,例如 400(错误请求)或 409(冲突)响应状态代码。 响应正文包含 JSON 格式的错误消息:

{
  "version": "1.0.0",
  "status": 409,
  "code": "API12345",
  "requestId": "50f0bd91-2ff4-4b8f-828f-00f170519ddb",
  "userMessage": "Message for the user",
  "developerMessage": "Verbose description of problem and how to fix it.",
  "moreInfo": "https://restapi/error/API12345/moreinfo"
}
特征 必选 DESCRIPTION
版本 是的 REST API 版本。 例如:1.0.1
地位 是的 HTTP 响应状态代码类似数字,并且必须为 409。 REST 服务可以返回 HTTP 4XX 状态代码,但在 JSON 格式的响应正文中提交的值 status 必须是 409。
代码 否 RESTful 终结点提供程序的错误代码,该提供程序在启用时 DebugMode 显示。
requestId 否 RESTful 终结点提供程序的请求标识符,启用时 DebugMode 会显示该标识符。
用户消息 是的 向用户显示的错误消息。
developerMessage 否 问题的详细说明以及如何修复该问题,该说明在启用时 DebugMode 显示。
moreInfo 否 指向其他信息的 URI,该信息在启用时 DebugMode 显示。

以下示例演示返回错误消息的 C# 类:

public class ResponseContent
{
  public string Version { get; set; }
  public int Status { get; set; }
  public string Code { get; set; }
  public string UserMessage { get; set; }
  public string DeveloperMessage { get; set; }
  public string RequestId { get; set; }
  public string MoreInfo { get; set; }
}