在 Azure Active Directory B2C 自定义策略中定义 RESTful 技术配置文件
注意
在 Azure Active Directory B2C 中,自定义策略主要用于解决复杂的情况。 在大多数情况下,建议你使用内置用户流。 如果尚未这样做,请从 Active Directory B2C 中的自定义策略入门了解自定义策略新手包。
Azure Active Directory B2C (Azure AD B2C) 为集成你自己的 RESTful 服务提供支持。 Azure AD B2C 在输入声明集合中将数据发送到 RESTful 服务,在输出声明集合中接收返回的数据。
协议
“Protocol”元素的“Name”属性必须设置为 Proprietary
。 handler 属性必须包含 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,而 surname 作为 lastName 发送。 email 声明的设置保留原样。
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" />
<InputClaim ClaimTypeReferenceId="givenName" PartnerClaimType="firstName" />
<InputClaim ClaimTypeReferenceId="surname" PartnerClaimType="lastName" />
</InputClaims>
InputClaimsTransformations 元素可以包含用于修改输入声明,或者先生成新输入声明,再将其发送到 REST API 的 InputClaimsTransformation 元素集合。
发送 JSON 有效负载
使用 REST API 技术配置文件可以将复杂的 JSON 有效负载发送到终结点。
发送复杂的 JSON 有效负载:
- 生成具备 GenerateJson 声明转换的 JSON 有效负载。
- 在 REST API 技术配置文件中执行以下操作:
- 添加具有对
GenerateJson
声明转换的引用的输入声明转换。 - 将
SendClaimsIn
元数据选项设置为body
- 将
ClaimUsedForRequestPayload
元数据选项设置为包含 JSON 有效负载的声明名称。 - 在输入声明中,添加对包含 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 中定义的名称。 如果设置了 DefaultValue
属性,则还可以包含 REST API 未返回的声明。
OutputClaimsTransformations 元素可能包含用于修改输出声明或生成新输出声明的 OutputClaimsTransformation 元素集合。
以下示例演示 REST API 返回的声明:
- 映射到 loyaltyNumber 声明名称的 MembershipId 声明。
技术配置文件还会返回标识提供者不返回的声明:
- 默认值设置为
true
的 loyaltyNumberIsNew 声明。
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="loyaltyNumber" PartnerClaimType="MembershipId" />
<OutputClaim ClaimTypeReferenceId="loyaltyNumberIsNew" DefaultValue="true" />
</OutputClaims>
Metadata
Attribute | 必须 | 说明 |
---|---|---|
ServiceUrl | 是 | REST API 终结点的 URL。 |
AuthenticationType | 是 | RESTful 声明提供程序所执行的身份验证类型。 可能的值:None 、Basic 、Bearer 、ClientCertificate 或 ApiKeyHeader 。
|
AllowInsecureAuthInProduction | 否 | 指示是否可以在生产环境中将 AuthenticationType 设置为 none (将 TrustFrameworkPolicy 的 DeploymentMode 设为 Production 或未指定)。 可能的值:true 或 false(默认值)。 |
SendClaimsIn | 否 | 指定如何将输入声明发送到 RESTful 声明提供程序。 可能的值:Body (默认值)、Form 、Header 、Url 或 QueryString 。 Body 值是在请求正文中以 JSON 格式发送的输入声明。 Form 值是在请求正文中以“&”分隔键值格式发送的输入声明。 Header 值是在请求标头中发送的输入声明。 Url 值是在 URL 中发送的输入声明,例如 https://api.example.com/{claim1}/{claim2}?{claim3}={claim4} 。 URL 的主机名部分不能包含声明。 QueryString 值是在请求查询字符串中发送的输入声明。 每个输入声明调用的 HTTP 谓词如下所示:
|
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 失败时显示的错误消息。 可以将错误消息本地化。
Attribute | 必须 | 说明 |
---|---|---|
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 元素包含以下属性:
属性 | 必须 | 说明 |
---|---|---|
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 元素包含以下属性:
属性 | 必须 | 说明 |
---|---|---|
ClientCertificate | 是 | 用于身份验证的 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 元素包含以下属性:
属性 | 必须 | 说明 |
---|---|---|
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 元素包含以下属性:
属性 | 必须 | 说明 |
---|---|---|
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"
}
属性 | 必须 | 说明 |
---|---|---|
版本 | 是 | REST API 版本。 例如:1.0.1 |
状态 | 是 | HTTP 响应状态代码等数字,必须为 409。 REST 服务可以返回 HTTP 4XX 状态代码,但在 JSON 格式的响应正文中提交的 status 值必须是 409 。 |
code | 否 | 来自 RESTful 终结点提供程序的错误代码,启用 DebugMode 后会显示。 |
requestId | 否 | 来自 RESTful 终结点提供程序的请求标识符,启用 DebugMode 后会显示。 |
userMessage | 是 | 向用户显示的错误消息。 |
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; }
}