如何在Azure AD B2C自定义策略中用客户端凭据传递查询参数
问题:Azure AD B2C客户端凭据流自定义策略无法识别查询参数
我正尝试使用客户端凭据(client_id和client_secret)访问Azure AD B2C的自定义策略以获取自定义JWT,目前已实现基础功能,但无法让自定义策略识别传递的查询参数。
当前配置与正常执行情况
我的自定义策略文件MyPolicy.xml内容如下:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <TrustFrameworkPolicy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/online/cpim/schemas/2013/06" PolicySchemaVersion="0.3.0.0" TenantId="{tenant}.onmicrosoft.com" PolicyId="B2C_1A_MyPolicy" PublicPolicyUri="http://{tenant}.onmicrosoft.com/B2C_1A_MyPolicy" DeploymentMode="Development" UserJourneyRecorderEndpoint="urn:journeyrecorder:applicationinsights"> <BasePolicy> <TenantId>{tenant}.onmicrosoft.com</TenantId> <PolicyId>B2C_1A_TrustFrameworkBase</PolicyId> </BasePolicy> <BuildingBlocks> <ClaimsSchema> <!-- JWT --> <ClaimType Id="value"> <DataType>string</DataType> </ClaimType> </ClaimsSchema> </BuildingBlocks> <ClaimsProviders> <ClaimsProvider> <DisplayName></DisplayName> <TechnicalProfiles> <TechnicalProfile Id="SetQueryParams"> <DisplayName>Set the BrandId and other query params from the OIDC:ClientId field in the url params</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Metadata> <Item Key="IncludeClaimResolvingInClaimsHandling">true</Item> </Metadata> <OutputClaims> <OutputClaim ClaimTypeReferenceId="value" DefaultValue="{OAUTH-KV:value}" AlwaysUseDefaultValue="true" /> </OutputClaims> <UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" /> </TechnicalProfile> </TechnicalProfiles> </ClaimsProvider> </ClaimsProviders> <UserJourneys> <UserJourney Id="MyUserJourney"> <OrchestrationSteps> <OrchestrationStep Order="1" Type="ClaimsExchange"> <ClaimsExchanges> <ClaimsExchange Id="SetQueryParamsStep" TechnicalProfileReferenceId="SetQueryParams" /> </ClaimsExchanges> </OrchestrationStep> <!-- Issue JWT --> <OrchestrationStep Order="2" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" /> </OrchestrationSteps> </UserJourney> </UserJourneys> <RelyingParty> <DefaultUserJourney ReferenceId="MyUserJourney" /> <UserJourneyBehaviors> <JourneyInsights TelemetryEngine="ApplicationInsights" InstrumentationKey="623badc9-900b-44e3-bd44-bf00d97d9d93" DeveloperMode="true" ClientEnabled="true" ServerEnabled="true" TelemetryVersion="1.0.0" /> <ScriptExecution>Allow</ScriptExecution> </UserJourneyBehaviors> <TechnicalProfile Id="PolicyProfile"> <DisplayName>PolicyProfile</DisplayName> <Protocol Name="OpenIdConnect" /> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub" AlwaysUseDefaultValue="true" DefaultValue="8186c7b3-adca-4c17-b318-939e9d8170b8" /> <OutputClaim ClaimTypeReferenceId="value" /> </OutputClaims> <SubjectNamingInfo ClaimType="sub" /> </TechnicalProfile> </RelyingParty> </TrustFrameworkPolicy>
我使用以下x-www-form-urlencoded格式的请求调用策略:
https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/B2C_1A_MyPolicy/oauth2/v2.0/token?grant_type=client_credentials&client_id=<appId>&client_secret=<client_secret>&scope=https://{tenant}.onmicrosoft.com/api/.default
此时策略可正常执行,返回包含硬编码默认值字段的JWT。
错误场景
当我修改RelyingParty部分,为value声明添加默认值{OAUTH-KV:value}后:
<RelyingParty> <DefaultUserJourney ReferenceId="MyUserJourney" /> <UserJourneyBehaviors> <JourneyInsights TelemetryEngine="ApplicationInsights" InstrumentationKey="{Settings:AppInsightsKey}" DeveloperMode="true" ClientEnabled="true" ServerEnabled="true" TelemetryVersion="1.0.0" /> <ScriptExecution>Allow</ScriptExecution> </UserJourneyBehaviors> <TechnicalProfile Id="PolicyProfile"> <DisplayName>PolicyProfile</DisplayName> <Protocol Name="OpenIdConnect" /> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub" AlwaysUseDefaultValue="true" DefaultValue="8186c7b3-adca-4c17-b318-939e9d8170b8" /> <OutputClaim ClaimTypeReferenceId="value" DefaultValue="{OAUTH-KV:value}" AlwaysUseDefaultValue="true" /> </OutputClaims> <SubjectNamingInfo ClaimType="sub" /> </TechnicalProfile> </RelyingParty>
调用后返回错误:
{ "error": "invalid_grant", "error_description": "AADB2C90085: The service has encountered an internal error. Please reauthenticate and try again.\r\nCorrelation ID: 1c7b50fa-87bb-4588-8ec0-90e8ed3554be\r\nTimestamp: 2022-12-18 22:05:45Z\r\n" }
我需要实现通过客户端凭据完成认证并传递自定义输入参数的功能,求解决方案。
解决方案
核心问题原因
在客户端凭据流中,RelyingParty的OpenIdConnect技术配置文件不支持直接使用{OAUTH-KV:}解析器,这会触发内部错误。另外,客户端凭据流的标准参数传递方式是表单体(x-www-form-urlencoded),而非URL查询字符串,这也会导致参数无法被正确捕获。
具体修复步骤
调整参数传递方式
将自定义参数value放在请求的表单体中,修改后的请求示例:POST https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/B2C_1A_MyPolicy/oauth2/v2.0/token Content-Type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=<appId>&client_secret=<client_secret>&scope=https://{tenant}.onmicrosoft.com/api/.default&value=your_custom_value修改参数解析器
在SetQueryParams技术配置文件中,使用{OAUTH-BODY:}解析器读取表单体中的参数,替换原有的{OAUTH-KV:}:<OutputClaim ClaimTypeReferenceId="value" DefaultValue="{OAUTH-BODY:value}" AlwaysUseDefaultValue="true" />恢复RelyingParty配置
移除RelyingParty中value声明的默认值配置,保持仅引用声明:<OutputClaim ClaimTypeReferenceId="value" />
完整修复后的关键配置片段
SetQueryParams技术配置文件
<TechnicalProfile Id="SetQueryParams"> <DisplayName>Set custom parameters from request body</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Metadata> <Item Key="IncludeClaimResolvingInClaimsHandling">true</Item> </Metadata> <OutputClaims> <OutputClaim ClaimTypeReferenceId="value" DefaultValue="{OAUTH-BODY:value}" AlwaysUseDefaultValue="true" /> </OutputClaims> <UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" /> </TechnicalProfile>RelyingParty部分
<RelyingParty> <DefaultUserJourney ReferenceId="MyUserJourney" /> <UserJourneyBehaviors> <JourneyInsights TelemetryEngine="ApplicationInsights" InstrumentationKey="623badc9-900b-44e3-bd44-bf00d97d9d93" DeveloperMode="true" ClientEnabled="true" ServerEnabled="true" TelemetryVersion="1.0.0" /> <ScriptExecution>Allow</ScriptExecution> </UserJourneyBehaviors> <TechnicalProfile Id="PolicyProfile"> <DisplayName>PolicyProfile</DisplayName> <Protocol Name="OpenIdConnect" /> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub" AlwaysUseDefaultValue="true" DefaultValue="8186c7b3-adca-4c17-b318-939e9d8170b8" /> <OutputClaim ClaimTypeReferenceId="value" /> </OutputClaims> <SubjectNamingInfo ClaimType="sub" /> </TechnicalProfile> </RelyingParty>
验证逻辑
- 部署修改后的自定义策略
- 使用表单体传递
value参数的POST请求调用token端点 - 检查返回的JWT,确认
value字段包含你传递的自定义值
内容的提问来源于stack exchange,提问作者Dessus
相关产品推荐
相关产品推荐

