Azure AD B2C IdP发起SSO:REST TP无法解析QueryString令牌
问题描述
我们正使用Azure AD B2C自定义策略构建IdP发起的SSO流程,流程需完成以下步骤:
- 读取3个QueryString参数:
enc_attrs_token、sp和EntityId; - 通过APIM将参数传递给后端REST API;
- 利用后端响应构建最终的SAML断言。
传入URL示例:https://<tenant>.b2clogin.com/<tenant>.onmicrosoft.com/B2C_1A_IdpSso/generic/login?EntityId=TP&enc_attrs_token=_TEST&sp=HD
我们尝试将REST技术配置文件作为首个编排步骤调用后端,期望{QueryString:*}令牌在请求体序列化前解析,但后端收到的是字面量而非实际参数值,即使已设置<Item Key="IncludeClaimResolvingInClaimsHandling">true</Item>。
疑问:Azure AD B2C是否存在此限制?需做哪些最小修改实现QueryString值预解析?
回答
关于限制说明
Azure AD B2C确实存在此限制:在首个编排步骤中直接使用{QueryString:*}令牌进行声明解析是不生效的。因为流程初始化阶段,声明解析引擎还未完成QueryString参数到声明的映射逻辑,此时这些令牌会被当作纯文本字面量处理,无法完成参数解析。
最小修改方案
核心思路是将「QueryString参数解析」和「REST API调用」拆分为两个独立的编排步骤,先完成参数到声明的映射,再将解析后的声明传递给API。
- 定义QueryString参数对应的声明类型
在策略的<BuildingBlocks>下的<ClaimTypes>节点中,添加三个声明的定义:
<ClaimType Id="enc_attrs_token"> <DisplayName>Encrypted Attributes Token</DisplayName> <DataType>string</DataType> </ClaimType> <ClaimType Id="sp"> <DisplayName>Service Provider</DisplayName> <DataType>string</DataType> </ClaimType> <ClaimType Id="EntityId"> <DisplayName>Entity ID</DisplayName> <DataType>string</DataType> </ClaimType>
- 添加QueryString解析的技术配置文件
在<ClaimsProviders>节点下,新增一个专门用于解析QueryString的声明提供程序:
<ClaimsProvider> <DisplayName>Query String Parser</DisplayName> <TechnicalProfiles> <TechnicalProfile Id="ParseQueryString"> <DisplayName>Parse Query String Parameters</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="enc_attrs_token" DefaultValue="{QueryString:enc_attrs_token}" /> <OutputClaim ClaimTypeReferenceId="sp" DefaultValue="{QueryString:sp}" /> <OutputClaim ClaimTypeReferenceId="EntityId" DefaultValue="{QueryString:EntityId}" /> </OutputClaims> </TechnicalProfile> </TechnicalProfiles> </ClaimsProvider>
- 调整编排步骤顺序
在对应的用户旅程中,将「QueryString解析」设为第一个编排步骤,之后再调用REST API:
<UserJourney Id="IdpInitiatedSso"> <OrchestrationSteps> <!-- 步骤1:解析QueryString参数为声明 --> <OrchestrationStep Order="1" Type="ClaimsExchange"> <ClaimsExchanges> <ClaimsExchange Id="ParseQueryStringExchange" TechnicalProfileReferenceId="ParseQueryString" /> </ClaimsExchanges> </OrchestrationStep> <!-- 步骤2:调用后端REST API(使用解析后的声明) --> <OrchestrationStep Order="2" Type="ClaimsExchange"> <ClaimsExchanges> <ClaimsExchange Id="CallRestApiExchange" TechnicalProfileReferenceId="YourRestApiTechnicalProfile" /> </ClaimsExchanges> </OrchestrationStep> <!-- 后续构建SAML断言等步骤... --> </OrchestrationSteps> </UserJourney>
- 修改REST技术配置文件
将原REST技术配置文件中引用{QueryString:*}的部分,替换为解析后的声明:
<TechnicalProfile Id="YourRestApiTechnicalProfile"> <DisplayName>Call Backend REST API via APIM</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-apim-instance.azure-api.net/backend-api/endpoint</Item> <Item Key="AuthenticationType">None</Item> <Item Key="SendClaimsIn">Body</Item> <Item Key="IncludeClaimResolvingInClaimsHandling">true</Item> </Metadata> <InputClaims> <InputClaim ClaimTypeReferenceId="enc_attrs_token" /> <InputClaim ClaimTypeReferenceId="sp" /> <InputClaim ClaimTypeReferenceId="EntityId" /> </InputClaims> <OutputClaims> <!-- 定义从API响应中获取的声明,用于后续构建SAML断言 --> </OutputClaims> </TechnicalProfile>
内容的提问来源于stack exchange,提问作者TNBG
相关产品推荐
相关产品推荐

