在 Azure Active Directory B2C 自定义策略中定义 RESTful 技术配置文件Define a RESTful technical profile in an Azure Active Directory B2C custom policy

备注

在 Azure Active Directory B2C 中,custom policies 主要用于解决复杂方案。In Azure Active Directory B2C, custom policies are designed primarily to address complex scenarios. 大多数情况下,建议使用内置的用户流For most scenarios, we recommend that you use built-in user flows.

Azure Active Directory B2C (Azure AD B2C) 为集成你自己的 RESTful 服务提供支持。Azure Active Directory B2C (Azure AD B2C) provides support for integrating your own RESTful service. Azure AD B2C 在输入声明集合中将数据发送到 RESTful 服务,在输出声明集合中接收返回的数据。Azure AD B2C sends data to the RESTful service in an input claims collection and receives data back in an output claims collection. 有关详细信息,请参阅在 Azure AD B2C 自定义策略中集成 REST API 声明交换For more information, see Integrate REST API claims exchanges in your Azure AD B2C custom policy.

协议Protocol

“Protocol”元素的“Name”属性必须设置为 ProprietaryThe Name attribute of the Protocol element needs to be set to Proprietary. handler 属性必须包含 Azure AD B2C 使用的协议处理程序程序集的完全限定名称:Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nullThe handler attribute must contain the fully qualified name of the protocol handler assembly that is used by Azure AD B2C: Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.

以下示例演示了一个 RESTful 技术配置文件:The following example shows a RESTful technical profile:

<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" />
  ...

输入声明Input claims

InputClaims 元素包含要发送到 REST API 的声明列表。The InputClaims element contains a list of claims to send to the REST API. 还可将声明名称映射到 REST API 中定义的名称。You can also map the name of your claim to the name defined in the REST API. 以下示例演示策略与 REST API 之间的映射。Following example shows the mapping between your policy and the REST API. givenName 声明作为 firstName 发送到 REST API,而 surname 作为 lastName 发送。The givenName claim is sent to the REST API as firstName, while surname is sent as lastName. email 声明的设置保留原样。The email claim is set as is.

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

InputClaimsTransformations 元素可以包含用于修改输入声明,或者先生成新输入声明,再将其发送到 REST API 的 InputClaimsTransformation 元素集合。The InputClaimsTransformations element may contain a collection of InputClaimsTransformation elements that are used to modify the input claims or generate new ones before sending to the REST API.

发送 JSON 有效负载Send a JSON payload

使用 REST API 技术配置文件可以将复杂的 JSON 有效负载发送到终结点。The REST API technical profile allows you to send a complex JSON payload to an endpoint.

发送复杂的 JSON 有效负载:To send a complex JSON payload:

  1. 生成具备 GenerateJson 声明转换的 JSON 有效负载。Build your JSON payload with the GenerateJson claims transformation.
  2. 在 REST API 技术配置文件中执行以下操作:In the REST API technical profile:
    1. 添加具有对 GenerateJson 声明转换的引用的输入声明转换。Add an input claims transformation with a reference to the GenerateJson claims transformation.
    2. SendClaimsIn 元数据选项设置为 bodySet the SendClaimsIn metadata option to body
    3. ClaimUsedForRequestPayload 元数据选项设置为包含 JSON 有效负载的声明名称。Set the ClaimUsedForRequestPayload metadata option to the name of the claim containing the JSON payload.
    4. 在输入声明中,添加对包含 JSON 有效负载的输入声明的引用。In the input claim, add a reference to the input claim containing the JSON payload.

以下示例 TechnicalProfile 使用第三方电子邮件服务(在本例中为 SendGrid)发送验证电子邮件。The following example TechnicalProfile sends a verification email by using a third-party email service (in this case, SendGrid).

<TechnicalProfile Id="SendGrid">
  <DisplayName>Use SendGrid's email API to send the code the 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>

输出声明Output claims

OutputClaims 元素包含 REST API 返回的声明列表。The OutputClaims element contains a list of claims returned by the REST API. 可能需要将策略中定义的声明名称映射到 REST API 中定义的名称。You may need to map the name of the claim defined in your policy to the name defined in the REST API. 如果设置了 DefaultValue 属性,则还可以包含 REST API 标识提供者不会返回的声明。You can also include claims that aren't returned by the REST API identity provider, as long as you set the DefaultValue attribute.

OutputClaimsTransformations 元素可能包含用于修改输出声明或生成新输出声明的 OutputClaimsTransformation 元素集合。The OutputClaimsTransformations element may contain a collection of OutputClaimsTransformation elements that are used to modify the output claims or generate new ones.

以下示例演示 REST API 返回的声明:The following example shows the claim returned by the REST API:

  • 映射到 loyaltyNumber 声明名称的 MembershipId 声明。The MembershipId claim that is mapped to the loyaltyNumber claim name.

技术配置文件还会返回标识提供者不返回的声明:The technical profile also returns claims, that aren't returned by the identity provider:

  • 默认值设置为 trueloyaltyNumberIsNew 声明。The loyaltyNumberIsNew claim that has a default value set to true.
<OutputClaims>
  <OutputClaim ClaimTypeReferenceId="loyaltyNumber" PartnerClaimType="MembershipId" />
  <OutputClaim ClaimTypeReferenceId="loyaltyNumberIsNew" DefaultValue="true" />
</OutputClaims>

MetadataMetadata

属性Attribute 必须Required 说明Description
ServiceUrlServiceUrl Yes REST API 终结点的 URL。The URL of the REST API endpoint.
AuthenticationTypeAuthenticationType Yes RESTful 声明提供程序所执行的身份验证类型。The type of authentication being performed by the RESTful claims provider. 可能的值:NoneBearerClientCertificatePossible values: None, Bearer, or ClientCertificate. None 值表示 REST API 不是匿名的。The None value indicates that the REST API is not anonymous. ClientCertificate(建议)值表示 REST API 使用客户端证书身份验证来限制访问。The ClientCertificate (recommended) value indicates that the REST API restricts access by using client certificate authentication. 只有包含相应证书的服务(例如 Azure AD B2C)才能访问你的 API。Only services that have the appropriate certificates, for example Azure AD B2C, can access your API. Bearer 值表示 REST API 使用客户端 OAuth2 持有者令牌来限制访问。The Bearer value indicates that the REST API restricts access using client OAuth2 Bearer token.
AllowInsecureAuthInProductionAllowInsecureAuthInProduction No 指示是否可以在生产环境中将 AuthenticationType 设置为 none(将 TrustFrameworkPolicyDeploymentMode 设为 Production 或未指定)。Indicates whether the AuthenticationType can be set to none in production environment (DeploymentMode of the TrustFrameworkPolicy is set to Production, or not specified). 可能的值:true 或 false(默认值)。Possible values: true, or false (default).
SendClaimsInSendClaimsIn No 指定如何将输入声明发送到 RESTful 声明提供程序。Specifies how the input claims are sent to the RESTful claims provider. 可能的值:Body(默认值)、FormHeaderUrlQueryStringPossible values: Body (default), Form, Header, Url or QueryString. Body 值是在请求正文中以 JSON 格式发送的输入声明。The Body value is the input claim that is sent in the request body in JSON format. Form 值是在请求正文中以“&”分隔键值格式发送的输入声明。The Form value is the input claim that is sent in the request body in an ampersand '&' separated key value format. Header 值是在请求标头中发送的输入声明。The Header value is the input claim that is sent in the request header. Url 值是在 URL 中发送的输入声明,例如 https://{claim1}.example.com/{claim2}/{claim3}?{claim4}={claim5}。The Url value is the input claim that is sent in the URL, for example, https://{claim1}.example.com/{claim2}/{claim3}?{claim4}={claim5}. QueryString 值是在请求查询字符串中发送的输入声明。The QueryString value is the input claim that is sent in the request query string. 每个输入声明调用的 HTTP 谓词如下所示:The HTTP verbs invoked by each are as follows:
  • Body:POSTBody: POST
  • Form:POSTForm: POST
  • Header:GETHeader: GET
  • Url:GETUrl: GET
  • QueryString:GETQueryString: GET
ClaimsFormatClaimsFormat No 当前未使用,可以忽略。Not currently used, can be ignored.
ClaimUsedForRequestPayloadClaimUsedForRequestPayload No 包含要发送到 REST API 的有效负载的字符串声明名称。Name of a string claim that contains the payload to be sent to the REST API.
DebugModeDebugMode No 在调试模式下运行技术配置文件。Runs the technical profile in debug mode. 可能的值:truefalse(默认值)。Possible values: true, or false (default). 在调试模式下,REST API 可以返回更多信息。In debug mode, the REST API can return more information. 请参阅返回错误消息部分。See the Returning error message section.
IncludeClaimResolvingInClaimsHandlingIncludeClaimResolvingInClaimsHandling   No 对于输入和输出声明,指定声明解析是否包含在技术配置文件中。For input and output claims, specifies whether claims resolution is included in the technical profile. 可能的值:truefalse (默认值)。Possible values: true, or false (default). 若要使用技术配置文件中的声明解析程序,请将此项设为 trueIf you want to use a claims resolver in the technical profile, set this to true.
ResolveJsonPathsInJsonTokensResolveJsonPathsInJsonTokens No 指示技术配置文件是否解析 JSON 路径。Indicates whether the technical profile resolves JSON paths. 可能的值:truefalse(默认值)。Possible values: true, or false (default). 使用此元数据从嵌套 JSON 元素中读取数据。Use this metadata to read data from a nested JSON element. OutputClaim 中,将 PartnerClaimType 设为要输出的 JSON 路径元素。In an OutputClaim, set the PartnerClaimType to the JSON path element you want to output. 例如:firstName.localizeddata.0.to.0.emailFor example: firstName.localized, or data.0.to.0.email.
UseClaimAsBearerTokenUseClaimAsBearerToken No 包含持有者令牌的声明的名称。The name of the claim that contains the bearer token.

错误处理。Error handling

以下元数据可用于配置 REST API 失败时显示的错误消息。The following metadata can be used to configure the error messages displayed upon REST API failure. 可以将错误消息本地化The error messages can be localized.

属性Attribute 必需Required 说明Description
DefaultUserMessageIfRequestFailedDefaultUserMessageIfRequestFailed No 所有 REST API 异常的默认自定义错误消息。A default customized error message for all REST API exceptions.
UserMessageIfCircuitOpenUserMessageIfCircuitOpen No 无法访问 REST API 时的错误消息。Error message when the REST API is not reachable. 如果未指定,则将返回 DefaultUserMessageIfRequestFailed。If not specified, the DefaultUserMessageIfRequestFailed will be returned.
UserMessageIfDnsResolutionFailedUserMessageIfDnsResolutionFailed No DNS 解析异常的错误消息。Error message for the DNS resolution exception. 如果未指定,则将返回 DefaultUserMessageIfRequestFailed。If not specified, the DefaultUserMessageIfRequestFailed will be returned.
UserMessageIfRequestTimeoutUserMessageIfRequestTimeout No 连接超时时的错误消息。如果未指定,则将返回 DefaultUserMessageIfRequestFailed。Error message when the connection is timed out. If not specified, the DefaultUserMessageIfRequestFailed will be returned.

加密密钥Cryptographic keys

如果身份验证类型设置为 None,则不使用 CryptographicKeys 元素。If the type of authentication is set to None, the CryptographicKeys element is not used.

<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>

如果身份验证类型设置为 ClientCertificate,则 CryptographicKeys 元素包含以下属性:If the type of authentication is set to ClientCertificate, the CryptographicKeys element contains the following attribute:

属性Attribute 必需Required 说明Description
ClientCertificateClientCertificate Yes 用于身份验证的 X509 证书(RSA 密钥集)。The X509 certificate (RSA key set) to use to authenticate.
<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 元素包含以下属性:If the type of authentication is set to Bearer, the CryptographicKeys element contains the following attribute:

属性Attribute 必需Required 说明Description
BearerAuthenticationTokenBearerAuthenticationToken No OAuth 2.0 持有者令牌。The OAuth 2.0 Bearer Token.
<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>

返回验证错误消息Returning validation error message

REST API 可能需要返回错误消息,例如“在 CRM 系统中未找到该用户”。Your REST API may need to return an error message, such as 'The user was not found in the CRM system'. 如果发生错误,REST API 应返回 HTTP 4xx 错误消息,例如“400 (错误请求)”或“409 (冲突)”响应状态代码。If an error occurs, the REST API should return an HTTP 4xx error message, such as, 400 (bad request), or 409 (conflict) response status code. 响应正文包含 JSON 格式的错误消息:The response body contains error message formatted in 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"
}
属性Attribute 必需Required 说明Description
版本version Yes REST API 版本。Your REST API version. 例如:1.0.1For example: 1.0.1
状态status Yes 必须为 409Must be 409
codecode No 来自 RESTful 终结点提供程序的错误代码,启用 DebugMode 后会显示。An error code from the RESTful endpoint provider, which is displayed when DebugMode is enabled.
requestIdrequestId No 来自 RESTful 终结点提供程序的请求标识符,启用 DebugMode 后会显示。A request identifier from the RESTful endpoint provider, which is displayed when DebugMode is enabled.
userMessageuserMessage Yes 向用户显示的错误消息。An error message that is shown to the user.
developerMessagedeveloperMessage No 问题的详细说明及其解决方法,启用 DebugMode 后会显示。The verbose description of the problem and how to fix it, which is displayed when DebugMode is enabled.
moreInfomoreInfo No 指向其他信息的 URI,启用 DebugMode 后会显示。A URI that points to additional information, which is displayed when DebugMode is enabled.

以下示例演示了一个返回错误消息的 C# 类:The following example shows a C# class that returns an error message:

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; }
}

后续步骤Next steps

有关使用 RESTful 技术配置文件的示例,请参阅以下文章:See the following articles for examples of using a RESTful technical profile: