Как в Azure AD B2C связать социальную учетную запись пользователя с уже существующей локальной учетной записью при первом входе в систему из социальной учетной записи?

Как я понял из документации, Azure AD B2C создает новую локальную учетную запись для каждого пользователя, который приходит из социальной учетной записи, такой как GMail/Facebook, во время первого входа (поправьте меня, если я не прав). Однако я хочу перехватить это и связать пользователя с уже существующей (собственной) локальной учетной записью без создания новой локальной учетной записи с помощью пользовательских политик.

2 ответа

Решение

Образец Wingtip содержит пример этого потока.

См. Файл проверяющей стороны "B2C_1A_link" и маршрут пользователя "Ссылка" для справки.

Обратите внимание, что эта поездка пользователя предлагает конечному пользователю войти в систему с локальной учетной записью, прежде чем он войдет в систему с социальной учетной записью.

Подробный образец приведен здесь.

Обновление "пользовательских идентификаторов" свяжет социальную учетную запись с локальной учетной записью.

Это может быть достигнуто путем перемещения пользователя, аналогичного приведенному ниже.

<UserJourney Id="AccountLinkage">
  <PreserveOriginalAssertion>false</PreserveOriginalAssertion>
  <OrchestrationSteps>
    <!-- Demo: The following orchestration step is always executed. 
         Asks user to sign-in with local account (only)-->
    <OrchestrationStep Order="1" Type="ClaimsProviderSelection" ContentDefinitionReferenceId="api.idpselections">
      <ClaimsProviderSelections>
        <ClaimsProviderSelection TargetClaimsExchangeId="LocalAccountSigninEmailExchange" />
      </ClaimsProviderSelections>
    </OrchestrationStep>

    <!-- Demo: Sign-in with local account-->
    <OrchestrationStep Order="2" Type="ClaimsExchange">
      <ClaimsExchanges>
        <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <!-- Demo: After user is sign-in, it reads the user, by user object ID,
         from the Azure AD identity store. An error is raised if the user does not exist. -->
    <OrchestrationStep Order="3" Type="ClaimsExchange">
      <ClaimsExchanges>
        <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <!-- Demo: After user is sign-in, and we have the user object ID.
        Now, ask the user to re-sign-in, but this time with
        one of the social account. This orchestration step, displays the sign-in with social
        account buttons.
        Note, You may want to add additional social accounts here-->
    <OrchestrationStep Order="4" Type="ClaimsProviderSelection" ContentDefinitionReferenceId="api.idpselections">
      <ClaimsProviderSelections>
        **<ClaimsProviderSelection TargetClaimsExchangeId="GoogleExchange" />
        <ClaimsProviderSelection TargetClaimsExchangeId="AmazonAccountExchange" />**
      </ClaimsProviderSelections>
    </OrchestrationStep>

    <!-- Demo: Run the sign-in with social account, based on user choice (from previous step)
        Note, You may want to add additional social accounts here -->
    <OrchestrationStep Order="5" Type="ClaimsExchange">
      <ClaimsExchanges>
        **<ClaimsExchange Id="GoogleExchange" TechnicalProfileReferenceId="Google-OAUTH" />
        <ClaimsExchange Id="AmazonAccountExchange" TechnicalProfileReferenceId="AmazonAccount-OAuth2" />**
      </ClaimsExchanges>
    </OrchestrationStep>

    <!-- Demo: Updates the social account for a user, identified by the object
         identifier for the user, in the Azure AD identity store. 
         An error is raised if the user does not exist. -->
    <OrchestrationStep Order="6" Type="ClaimsExchange">
      <ClaimsExchanges>
        <ClaimsExchange Id="AAD-UserWriteUsingAlternativeSecurityId-ThrowIfNotExists" TechnicalProfileReferenceId="AAD-UserWriteUsingAlternativeSecurityId-ThrowIfNotExists" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <!-- Demo: Re-reads the user, by user object Id, from the Azure Active Directory.
         An error is raised if the user does not exist. -->
    <OrchestrationStep Order="7" Type="ClaimsExchange">
      <ClaimsExchanges>
        <ClaimsExchange Id="AADUserReadWithObjectIdAfter" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <!-- Demo: Issues a JWT token to the relying party. -->
    <OrchestrationStep Order="8" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
  </OrchestrationSteps>
</UserJourney>

Затем создайте политику 'LinkExternalAccount.xml', аналогичную приведенной ниже.

<RelyingParty>
<!-- Demo: This relying party policy executes the `AccountLinkage` user journey.
Please see the B2C_1A_Link_TrustFrameworkExtensions policy for more details -->
<DefaultUserJourney ReferenceId="AccountLinkage" />
<TechnicalProfile Id="PolicyProfile">
  <DisplayName>PolicyProfile</DisplayName>
  <Protocol Name="OpenIdConnect" />
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="displayName" />
    <OutputClaim ClaimTypeReferenceId="givenName" />
    <OutputClaim ClaimTypeReferenceId="surname" />
    <OutputClaim ClaimTypeReferenceId="email" />
    <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub"/>
    <OutputClaim ClaimTypeReferenceId="identityProvider" />
  </OutputClaims>
  <SubjectNamingInfo ClaimType="sub" />
</TechnicalProfile>

Как только мы запустим наш Linkexternalaccount.xml, он будет перенаправлен на нашу локальную учетную запись, а после успешной регистрации он запросит выбор IDP и на основе выбранного пользователя будет обновлен атрибут "Идентификационные данные пользователя". Мы можем проверить то же самое, опрашивая пользователя. Пример идентификатора пользователя выглядит следующим образом:

 **"userIdentities": [
    {
        "issuer": "google.com",
        "issuerUserId": "MTA5MjA5ODQwNzAyNjc3NTEzMzM5"
    }**