Azure AD B2C - 具有 HRD、域提示和 MFA 的自定义策略

Azure AD B2C - Custom policy with HRD, Domain Hints and MFA

我正在尝试构建一个使用主领域发现和域提示的 B2C 自定义策略。

我们有 2 个角色。

  1. 在 B2C 中使用 MFA 进行身份验证的本地用户
  2. 必须重定向到其公司登录页面的外部用户。

用例:

  1. 用户被重定向到 https://customdomain.b2clogin.com(无域提示)。 用户会看到一个登录页面,要求输入 email 地址,具体取决于用户类型:

    • B2C 的本地用户在我们的 B2C 页面中进行身份验证 (自定义域。b2clogin.com)。首先,用户输入电子邮件地址, 然后在 Next 用户输入密码,最后输入代码(在 phone 收到) 对于 MFA。

    • 外部用户首先输入他们的电子邮件,然后 B2C 必须 自动将用户重定向到联合身份提供程序以登录。

  2. 用户被重定向到 https://customdomain.b2clogin.com/?domain_hint=xyz.com(带域提示)

    • 在这种情况下,我们希望用户自动重定向到 xyz.com 身份提供者。用户不应看到 customdomain.b2clogin.com
    • 的登录页面

我尝试过的:

通过使用 home-realm-discovery-modern 示例 (https://github.com/azure-ad-b2c/samples/tree/master/policies/home-realm-discovery-modern),我可以让 HRD 正常工作(第 1 点)

通过使用 B2C 入门包中的 SocialAndLocalAccountsWithMfa 示例,我可以免费获得 domain_hint 重定向(上面的第 2 点)。

但是,我未能将两者结合起来使两者都起作用(domain_hint 和 HRD)。

这是用户旅程:

    <UserJourneys>
       <UserJourney Id="SignIn">

        <OrchestrationSteps>

            <OrchestrationStep Order="1" Type="ClaimsExchange">
                <ClaimsExchanges>
                    <ClaimsExchange Id="ParseDomainHint" TechnicalProfileReferenceId="ParseDomainHint" />
                </ClaimsExchanges>
            </OrchestrationStep>

            <OrchestrationStep Order="2" Type="ClaimsExchange">
                <Preconditions>
                    <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
                        <Value>isKnownCustomer</Value>
                        <Value>True</Value>
                        <Action>SkipThisOrchestrationStep</Action>
                    </Precondition>
                </Preconditions>
                <ClaimsExchanges>
                    <ClaimsExchange Id="SigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-Signin-Email" />
                </ClaimsExchanges>
            </OrchestrationStep> 

            <OrchestrationStep Order="3" Type="ClaimsExchange">
                <Preconditions>
                    <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
                        <Value>isKnownCustomer</Value>
                        <Value>True</Value>
                        <Action>SkipThisOrchestrationStep</Action>
                    </Precondition>
                </Preconditions>
                <ClaimsExchanges>
                    <ClaimsExchange Id="ParseDomainHintLogic" TechnicalProfileReferenceId="HRDLogic" />
                </ClaimsExchanges>
            </OrchestrationStep>

            <!-- If the domain_hint did not match any known domain, then redirect to a default local account sign in-->
            <OrchestrationStep Order="4" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin">
                <Preconditions>
                    <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
                        <Value>isKnownCustomer</Value>
                        <Value>True</Value>
                        <Action>SkipThisOrchestrationStep</Action>
                    </Precondition>
                </Preconditions>
                <ClaimsProviderSelections>
                    <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
                </ClaimsProviderSelections>
                <ClaimsExchanges>
                    <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
                </ClaimsExchanges>
            </OrchestrationStep>

            <!-- dont run this step if the domain was known, or we have an objectid (local account sign in)-->
            <OrchestrationStep Order="5" Type="ClaimsExchange">
                <Preconditions>
                    <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
                        <Value>objectId</Value>
                        <Action>SkipThisOrchestrationStep</Action>
                    </Precondition>
                    <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
                        <Value>isKnownCustomer</Value>
                        <Value>true</Value>
                        <Action>SkipThisOrchestrationStep</Action>
                    </Precondition>
                </Preconditions>
                <ClaimsExchanges>
                    <ClaimsExchange Id="SignUpWithLogonEmailExchange" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonEmail" />
                </ClaimsExchanges>
            </OrchestrationStep>

            <!-- If the domain matched any known domain, then this step will have a single IdP
                enabled due to each known IdP TP having an enablement flag via identityProviders claim -->
            <OrchestrationStep Order="6" Type="ClaimsProviderSelection" ContentDefinitionReferenceId="api.idpselections">
                <Preconditions>
                    <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
                        <Value>isKnownCustomer</Value>
                        <Value>True</Value>
                        <Action>SkipThisOrchestrationStep</Action>
                    </Precondition>
                </Preconditions>
                <ClaimsProviderSelections>
                    <ClaimsProviderSelection TargetClaimsExchangeId="AADOIDC" />
                    <ClaimsProviderSelection TargetClaimsExchangeId="MSAOIDC" />
                </ClaimsProviderSelections>
            </OrchestrationStep>

            <OrchestrationStep Order="7" Type="ClaimsExchange">
                <Preconditions>
                    <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
                        <Value>objectId</Value>
                        <Action>SkipThisOrchestrationStep</Action>
                    </Precondition>
                    <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
                        <Value>isKnownCustomer</Value>
                        <Value>true</Value>
                        <Action>SkipThisOrchestrationStep</Action>
                    </Precondition>
                </Preconditions>
                <ClaimsExchanges>
                    <ClaimsExchange Id="AADOIDC" TechnicalProfileReferenceId="AAD-OIDC" />
                    <ClaimsExchange Id="MSAOIDC" TechnicalProfileReferenceId="MSA-OIDC" />
                </ClaimsExchanges>
            </OrchestrationStep>

            <!-- For social IDP authentication, attempt to find the user account in the directory. -->
            <OrchestrationStep Order="8" Type="ClaimsExchange">
                <Preconditions>
                    <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
                        <Value>isKnownCustomer</Value>
                        <Value>True</Value>
                        <Action>SkipThisOrchestrationStep</Action>
                    </Precondition>
                </Preconditions>
                <ClaimsExchanges>
                    <ClaimsExchange Id="AADUserReadUsingAlternativeSecurityId" TechnicalProfileReferenceId="AAD-UserReadUsingAlternativeSecurityId-NoError" />
                </ClaimsExchanges>
            </OrchestrationStep>

            <!-- Still dont have objectId (social idp user that doesnt yet exist) - write the account -->
            <OrchestrationStep Order="9" Type="ClaimsExchange">
                <Preconditions>
                    <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
                        <Value>objectId</Value>
                        <Action>SkipThisOrchestrationStep</Action>
                    </Precondition>
                </Preconditions>
                <ClaimsExchanges>
                    <ClaimsExchange Id="AADUserWrite" TechnicalProfileReferenceId="AAD-UserWriteUsingAlternativeSecurityId" />
                </ClaimsExchanges>
            </OrchestrationStep>

            <OrchestrationStep Order="10" Type="ClaimsExchange">
                <Preconditions>
                    <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
                        <Value>isKnownCustomer</Value>
                        <Value>True</Value>
                        <Action>SkipThisOrchestrationStep</Action>
                    </Precondition>
                </Preconditions>
                <ClaimsExchanges>
                    <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
                </ClaimsExchanges>
            </OrchestrationStep>

            <OrchestrationStep Order="11" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
        </OrchestrationSteps>
        <ClientDefinition ReferenceId="DefaultWeb" />
    </UserJourney>
</UserJourneys>

我错过了什么?

我们设法让 Home Realm Discovery (HRD) 和域提示在自定义策略中协同工作。它基于 HomeRealmDiscoveryModern 示例。

这是 solution/sample: https://github.com/AlbozDroid/b2c-hrd-domainhint-sample/blob/main/Alboz_susi_public.xml

MFA 部分不存在,但按照 Microsoft 提供的 LocalAndSocialWithMFA 示例应该很容易添加。