You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure AD B2C自定义注册政策无法读取URL查询参数预填输入框

Azure AD B2C 注册政策预填URL参数失败的问题排查与修复

你遇到的问题核心出在入口政策未捕获URL参数和缺失姓氏声明定义两个关键点上,以下是具体分析和修复方案:

问题1:RelyingParty未配置输入声明捕获URL参数

你的依赖方(RelyingParty)是政策的入口,当前仅配置了输出声明,没有定义InputClaims来接收URL中的查询参数。这导致参数根本无法进入政策流程,SelfAsserted技术配置文件自然读取不到值,只能显示默认的{QueryString:xxx}占位符。

另外,你提到使用OAuth2协议,但RelyingParty里的TechnicalProfile协议是OpenIdConnect,虽然两者兼容,但需要明确协议类型并配置参数传递规则。

问题2:ClaimsSchema缺失姓氏声明

你的ClaimsSchema仅定义了email和givenName,没有surName(AD B2C标准的姓氏声明ID为surName,注意大小写),即使参数传过来,也没有对应的声明类型存储值。


修复后的完整政策代码

<?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="yourtenant.onmicrosoft.com"
        PolicyId="B2C_1A_TrustFrameworkExtensions"
        PublicPolicyUri="http://yourtenant.onmicrosoft.com/B2C_1A_TrustFrameworkExtensions">
    
    <BasePolicy>
        <TenantId>yourtenant.onmicrosoft.com</TenantId>
        <PolicyId>B2C_1A_TrustFrameworkBase</PolicyId>
    </BasePolicy>
    
    <BuildingBlocks>
        <ClaimsSchema>
            <ClaimType Id="email">
                <DisplayName>Email Address</DisplayName>
                <DataType>string</DataType>
                <DefaultPartnerClaimTypes>
                    <Protocol Name="OAuth2" PartnerClaimType="email" />
                </DefaultPartnerClaimTypes>
                <UserHelpText>Your email address</UserHelpText>
                <UserInputType>TextBox</UserInputType>
            </ClaimType>
            
            <ClaimType Id="givenName">
                <DisplayName>Given Name</DisplayName>
                <DataType>string</DataType>
                <DefaultPartnerClaimTypes>
                    <Protocol Name="OAuth2" PartnerClaimType="given_name" />
                </DefaultPartnerClaimTypes>
                <UserHelpText>Your given name</UserHelpText>
                <UserInputType>TextBox</UserInputType>
            </ClaimType>

            <!-- 新增姓氏声明定义 -->
            <ClaimType Id="surName">
                <DisplayName>Surname</DisplayName>
                <DataType>string</DataType>
                <DefaultPartnerClaimTypes>
                    <Protocol Name="OAuth2" PartnerClaimType="surname" />
                </DefaultPartnerClaimTypes>
                <UserHelpText>Your surname</UserHelpText>
                <UserInputType>TextBox</UserInputType>
            </ClaimType>

        </ClaimsSchema>
    </BuildingBlocks>
    
    <ClaimsProviders>
        <ClaimsProvider>
            <DisplayName>Self Asserted</DisplayName>
            <TechnicalProfiles>
                <TechnicalProfile Id="SelfAsserted-SignUp">
                    <DisplayName>User Sign-Up</DisplayName>
                    <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
                    <Metadata>
                        <Item Key="ContentDefinitionReferenceId">api.selfasserted</Item>
                        <Item Key="IncludeClaimResolvingInClaimsHandling">true</Item>
                    </Metadata>
                    <InputClaims>
                        <!-- 统一使用surName作为声明ID -->
                        <InputClaim ClaimTypeReferenceId="email" DefaultValue="{QueryString:email}" AlwaysUseDefaultValue="true" />
                        <InputClaim ClaimTypeReferenceId="givenName" DefaultValue="{QueryString:given_name}" AlwaysUseDefaultValue="true" />
                        <InputClaim ClaimTypeReferenceId="surName" DefaultValue="{QueryString:surname}" AlwaysUseDefaultValue="true" />
                    </InputClaims>
                    <OutputClaims>
                        <OutputClaim ClaimTypeReferenceId="email" Required="true" />
                        <OutputClaim ClaimTypeReferenceId="givenName" />
                        <OutputClaim ClaimTypeReferenceId="surName" />
                    </OutputClaims>
                    <ValidationTechnicalProfiles>
                        <ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonEmail" />
                    </ValidationTechnicalProfiles>
                </TechnicalProfile>
            </TechnicalProfiles>
        </ClaimsProvider>
        
        <ClaimsProvider>
            <DisplayName>Azure Active Directory</DisplayName>
            <TechnicalProfiles>
                <TechnicalProfile Id="AAD-UserWriteUsingLogonEmail">
                    <DisplayName>Write user to Azure AD B2C using email</DisplayName>
                    <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.AzureActiveDirectory.AzureActiveDirectoryIdentityProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
                    <Metadata>
                        <Item Key="Operation">Write</Item>
                        <Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">true</Item>
                        <Item Key="UserMessageIfClaimsPrincipalAlreadyExists">An account with this email already exists.</Item>
                    </Metadata>
                    <InputClaims>
                        <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" Required="true" />
                        <InputClaim ClaimTypeReferenceId="givenName" />
                        <InputClaim ClaimTypeReferenceId="surName" />
                    </InputClaims>
                    <PersistedClaims>
                        <PersistedClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" />
                        <PersistedClaim ClaimTypeReferenceId="givenName" />
                        <PersistedClaim ClaimTypeReferenceId="surName" />
                    </PersistedClaims>
                    <OutputClaims>
                        <OutputClaim ClaimTypeReferenceId="objectId" />
                    </OutputClaims>
                </TechnicalProfile>
            </TechnicalProfiles>
        </ClaimsProvider>
    </ClaimsProviders>

    <!-- User Journeys -->
    <UserJourneys>
        <UserJourney Id="SignUpJourney">
            <OrchestrationSteps>
                <OrchestrationStep Order="1" Type="ClaimsExchange">
                    <ClaimsExchanges>
                        <ClaimsExchange Id="SelfAsserted-SignUp" TechnicalProfileReferenceId="SelfAsserted-SignUp" />
                    </ClaimsExchanges>
                </OrchestrationStep>
                
                <OrchestrationStep Order="2" Type="ClaimsExchange">
                    <ClaimsExchanges>
                        <ClaimsExchange Id="AADUserWrite" TechnicalProfileReferenceId="AAD-UserWriteUsingLogonEmail" />
                    </ClaimsExchanges>
                </OrchestrationStep>
                
                <OrchestrationStep Order="3" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
            </OrchestrationSteps>
        </UserJourney>
    </UserJourneys>
    
    <RelyingParty>
        <DefaultUserJourney ReferenceId="SignUpJourney" />
        <TechnicalProfile Id="PolicyProfile">
            <DisplayName>Sign Up Policy</DisplayName>
            <Protocol Name="OAuth2" /> <!-- 匹配你使用的OAuth2协议 -->
            <!-- 新增InputClaims捕获URL参数,传入政策流程 -->
            <InputClaims>
                <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="email" />
                <InputClaim ClaimTypeReferenceId="givenName" PartnerClaimType="given_name" />
                <InputClaim ClaimTypeReferenceId="surName" PartnerClaimType="surname" />
            </InputClaims>
            <OutputClaims>
                <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub" />
                <OutputClaim ClaimTypeReferenceId="email" />
                <OutputClaim ClaimTypeReferenceId="givenName" />
                <OutputClaim ClaimTypeReferenceId="surName" />
            </OutputClaims>
            <SubjectNamingInfo ClaimType="sub" />
        </TechnicalProfile>
    </RelyingParty>

</TrustFrameworkPolicy>

关键修改说明

  1. 新增surName声明:在ClaimsSchema中添加标准的姓氏声明,确保能存储URL传入的surname参数。
  2. RelyingParty配置参数捕获:将协议改为OAuth2,并添加InputClaims捕获URL中的三个参数,让参数进入政策流程。
  3. 统一声明ID引用:所有涉及姓氏的地方统一使用surName作为声明ID,避免不匹配导致的值丢失。

测试方式

使用类似以下URL访问注册页面(替换为你的租户、政策ID和客户端信息):

https://yourtenant.b2clogin.com/yourtenant.onmicrosoft.com/oauth2/v2.0/authorize?p=B2C_1A_TrustFrameworkExtensions&client_id=your-client-id&nonce=defaultNonce&redirect_uri=https://your-app-redirect-uri&scope=openid&response_type=code&prompt=login&email=test@example.com&given_name=John&surname=Doe

内容的提问来源于stack exchange,提问作者HelpAStudentOut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 14:22:03