如何从Azure AD B2C发送带SessionIndex的SAML LogoutRequest?
一、优先方案:让B2C自动触发SAML单点登出(SLO)
你已经在SAML IdP技术配置中开启了SingleLogoutEnabled="true",但还需要调整会话管理配置并补充用户旅程逻辑,才能让B2C自动生成并发送LogoutRequest:
修正SAML会话管理配置
把会话管理技术配置里的IncludeSessionIndex和RegisterServiceProviders设为true,确保B2C存储SAML响应中的SessionIndex并注册服务提供商信息:<ClaimsProvider> <DisplayName>Session Management</DisplayName> <TechnicalProfiles> <TechnicalProfile Id="SM-Saml-idp"> <DisplayName>Session Management Provider</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.SSO.SamlSSOSessionProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Metadata> <Item Key="IncludeSessionIndex">true</Item> <Item Key="RegisterServiceProviders">true</Item> </Metadata> </TechnicalProfile> </TechnicalProfiles> </ClaimsProvider>完善登出用户旅程配置
创建单独的登出用户旅程,或者在现有用户旅程的末尾添加步骤触发SLO:<!-- 示例登出用户旅程步骤 --> <OrchestrationStep Order="1" Type="Logout" ContentDefinitionReferenceId="api.signuporsignin"> <ClaimsProviderSelections> <ClaimsProviderSelection TargetClaimsExchangeId="SAMLIdPLogout" /> </ClaimsProviderSelections> </OrchestrationStep> <OrchestrationStep Order="2" Type="ClaimsExchange"> <ClaimsExchanges> <ClaimsExchange Id="SAMLIdPLogout" TechnicalProfileReferenceId="SAML2-IdP" /> </ClaimsExchanges> </OrchestrationStep>B2C会自动根据IdP元数据中的SingleLogoutService地址,生成包含EntityID、IssueInstant、NameID和SessionIndex的LogoutRequest,并使用正确的绑定(HTTP-POST/HTTP-Redirect)发送给IdP。
验证签名与解密配置
确保SamlMessageSigning密钥正确配置,满足IdP对SignedRequests的要求;同时确认SamlAssertionDecryption密钥能正确解密IdP的加密断言,否则B2C无法读取SessionIndex。
二、替代方案:提取SessionIndex到声明,由应用端发送LogoutRequest
如果B2C自动SLO无法满足需求,可以通过声明解析器直接提取AuthnStatement中的SessionIndex,返回给应用后由应用自行构造LogoutRequest:
定义SessionIndex声明类型
在信任框架的<ClaimsSchema>中添加声明:<ClaimType Id="sessionIndex"> <DisplayName>Session Index</DisplayName> <DataType>string</DataType> <UserHelpText>从SAML认证响应中获取的会话索引</UserHelpText> </ClaimType>添加声明提取逻辑
在SAML IdP技术配置的<OutputClaims>中,使用声明解析器直接从SAML响应XML中提取SessionIndex:<OutputClaim ClaimTypeReferenceId="sessionIndex" DefaultValue="{ClaimResolver:SamlResponse:AuthnStatement:SessionIndex}" />这个解析器会跳过默认的AttributeStatement提取逻辑,直接读取AuthnStatement节点的SessionIndex属性值。
将SessionIndex返回给应用
在用户旅程的输出声明中包含sessionIndex,应用拿到该值后,即可按照IdP要求构造SAML LogoutRequest,包含所需的EntityID、IssueInstant、NameID和SessionIndex,发送到IdP的SingleLogoutService地址。
排查要点
- 若设置
IncludeSessionIndex="true"后仍无法获取SessionIndex,检查IdP的SAML响应是否确实在AuthnStatement中包含该字段,同时确认B2C的断言解密配置正确(因为你开启了WantsEncryptedAssertions="true")。 - 确认IdP元数据中的SingleLogoutService绑定(HTTP-POST/HTTP-Redirect)能被B2C正确识别,B2C会自动选择适配的绑定方式。
内容的提问来源于stack exchange,提问作者Columbarius

