How to pre-create “business customers” in AD B2C

2019-07-26 04:20发布

I'm building an on-boarding webapp to provision users for my LOB app. Most of my customers are "business customers", meaning they will ordinarily be directed to the v1 common endpoint by a custom policy, allowing them to auth against their own AAD tenant. The challenge is new users need follow-on provisioning in the LOB app as well (create db user, assign some permissions, etc).

What I'd like to do as part of on-boarding is call graphAPI to create what will become the federated user account in b2c, then with the new user objectId that comes back handle follow-on setup specific to my LOB app. Ideally when the user arrives for the first time, they would be redirected to auth against their own AAD, then map to the pre-created user in b2c, and finally land in the LOB app with an objectId that is already provisioned and ready.

Is this a supported scenario with some creative use of custom policies and graphAPI?

Thanks Mark

1条回答
家丑人穷心不美
2楼-- · 2019-07-26 04:56

You have the following options for this:

  1. Create a local account user with the external email address and link the external user identity with this local account user.
  2. Create an external account user with the external user identity.

1. Create a local account user with the external email address

Using Azure AD Graph API, you can create a local account user, with the signInNames property of the user object being set to the email address of the external user:

{
  "accountEnabled": false,
  "creationType": "LocalAccount",
  "displayName": "John Smith",
  "passwordProfile": {
    "password": "a-strong-random-password",
    "forceChangePasswordNextLogin": false
  }
  "signInNames": [
    {
      "type": "emailAddress",
      "value": "john.smith@company.com"
    }
  ]
}

Note: I recommend the accountEnabled property of the user object is set to true so that the end user can't log in with the local account password.

Using a custom policy, you can then add a new logic to find the local account user using the external email address and add the external user identity to this local account user, such as:

...
<!--
      Find the external account user using the external user identity.
-->
<OrchestrationStep Order="16" Type="ClaimsExchange">
  <Preconditions>
    <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
      <Value>authenticationSource</Value>
      <Value>localAccountAuthentication</Value>
      <Action>SkipThisOrchestrationStep</Action>
    </Precondition>
  </Preconditions>
  <ClaimsExchanges>
    <ClaimsExchange Id="AADUserReadUsingAlternativeSecurityId" TechnicalProfileReferenceId="AAD-UserReadUsingAlternativeSecurityId-NoError" />
  </ClaimsExchanges>
</OrchestrationStep>
<!--
      If the external account user hasn't been found, then find the local account user using the external email address.
-->
<OrchestrationStep Order="17" Type="ClaimsExchange">
  <Preconditions>
    <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
      <Value>authenticationSource</Value>
      <Value>localAccountAuthentication</Value>
      <Action>SkipThisOrchestrationStep</Action>
    </Precondition>
    <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
      <Value>objectId</Value>
      <Action>SkipThisOrchestrationStep</Action>
    </Precondition>
  </Preconditions>
  <ClaimsExchanges>
    <ClaimsExchange Id="AADUserReadUsingEmailAddress" TechnicalProfileReferenceId="AAD-UserReadUsingEmailAddress-NoError" />
  </ClaimsExchanges>
</OrchestrationStep>
<!--
      If an account user hasn't been found, then create an external account user with the external user identity.
-->
<OrchestrationStep Order="18" Type="ClaimsExchange">
  <Preconditions>
    <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
      <Value>authenticationSource</Value>
      <Value>localAccountAuthentication</Value>
      <Action>SkipThisOrchestrationStep</Action>
    </Precondition>
    <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
      <Value>objectId</Value>
      <Action>SkipThisOrchestrationStep</Action>
    </Precondition>
  </Preconditions>
  <ClaimsExchanges>
    <ClaimsExchange Id="AADUserWriteUsingAlternativeSecurityId" TechnicalProfileReferenceId="AAD-UserWriteUsingAlternativeSecurityId" />
  </ClaimsExchanges>
</OrchestrationStep>
<!--
      If the local account user has been found using the external email address, then add the external user identity to this local account user.
-->
<OrchestrationStep Order="19" Type="ClaimsExchange">
  <Preconditions>
    <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
      <Value>authenticationSource</Value>
      <Value>localAccountAuthentication</Value>
      <Action>SkipThisOrchestrationStep</Action>
    </Precondition>
    <!-- The following claim is output from the AAD-UserWriteUsingAlternativeSecurityId technical profile. -->
    <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
      <Value>newUserCreated</Value>
      <Action>SkipThisOrchestrationStep</Action>
    </Precondition>
    <!-- The following claim is output from the AAD-UserReadUsingEmailAddress-NoError technical profile. -->
    <Precondition Type="ClaimsExist" ExecuteActionsIf="false">
      <Value>existingUserFoundByEmail</Value>
      <Action>SkipThisOrchestrationStep</Action>
    </Precondition>
  </Preconditions>
  <ClaimsExchanges>
    <ClaimsExchange Id="AADUserWriteUserIdentity" TechnicalProfileReferenceId="AAD-UserWriteUserIdentity" />
  </ClaimsExchanges>
</OrchestrationStep>
...

2. Create an external account user with the external user identity

Using Azure AD Graph API, you can create an external account user, with the userIdentities property of the user object being set to the object identifier of the external user:

{
  "accountEnabled": false,
  "displayName": "John Smith",
  "mailNickname": "john.smith",
  "otherMails": [
    "john.smith@company.com"
  ],
  "userIdentities": [
    {
      "issuer": "https://sts.windows.net/{their-tenant-object-id}/",
      "issuerUserId": "{their-user-object-id}"
    }
  ],
  "userPrincipalName": "{guid}@{your-tenant-name}.onmicrosoft.com"
}

where issuerUserId must be set to the base64 encoding for the object identifier of the external user.

Note: In the Azure AD OpenID Connect technical profile, you might have to change the claim mapping for the socialIdpUserId claim from the sub claim to the oid claim, so that it matches the userIdentities.issuerUserId property of the user object:

<OutputClaim ClaimTypeReferenceId="socialIdpUserId" PartnerClaimType="oid" />
查看更多
登录 后发表回答