2
votes

I use the following PowerShell to create B2B users for an app that doesn't allow self signup. The tenant allows self service password resets and requires MFA.

# B2C allows you to sign in either with your user name or email address (not both for some reason)
$SignInNames = @(
    (New-Object `
        Microsoft.Open.AzureAD.Model.SignInName `
        -Property @{Type = "userName"; Value = $UserName}),
    (New-Object `
        Microsoft.Open.AzureAD.Model.SignInName `
        -Property @{Type = "emailAddress"; Value = $EmailAddress})
)

# I can't actually sign in with this user. 
$PasswordProfile = New-Object `
    -TypeName Microsoft.Open.AzureAD.Model.PasswordProfile `
    -Property @{ 
        'Password' = $Password;
        'ForceChangePasswordNextLogin' = $true;
    };

New-AzureADUser `
    -DisplayName $UserName.Replace('_', ' ') `
    -CreationType "LocalAccount" `
    -AccountEnabled $true `
    -PasswordProfile $PasswordProfile `
    -PasswordPolicies "DisablePasswordExpiration" `
    -SignInNames $SignInNames

The user is created, but the password I used does not work. The user can use self service password reset, which will prompt them for their phone number for MFA.

If I search for local users with the following Azure Graph call:

https://graph.windows.net/{{tenantId}}/users/?api-version=1.6&$filter=creationType eq 'LocalAccount' I see the user like so:

{
        "odata.type": "Microsoft.DirectoryServices.User",
        "objectType": "User",
        "objectId": "__OBJECT_ID__",
        "deletionTimestamp": null,
        "accountEnabled": true,
        "ageGroup": null,
        "assignedLicenses": [],
        "assignedPlans": [],
        "city": null,
        "companyName": null,
        "consentProvidedForMinor": null,
        "country": null,
        "creationType": "LocalAccount",
        "department": null,
        "dirSyncEnabled": null,
        "displayName": "Justin Dearing",
        "employeeId": null,
        "facsimileTelephoneNumber": null,
        "givenName": null,
        "immutableId": null,
        "isCompromised": null,
        "jobTitle": null,
        "lastDirSyncTime": null,
        "legalAgeGroupClassification": null,
        "mail": null,
        "mailNickname": "__MAIL_NICKNAME__",
        "mobile": null,
        "onPremisesDistinguishedName": null,
        "onPremisesSecurityIdentifier": null,
        "otherMails": [],
        "passwordPolicies": null,
        "passwordProfile": null,
        "physicalDeliveryOfficeName": null,
        "postalCode": null,
        "preferredLanguage": null,
        "provisionedPlans": [],
        "provisioningErrors": [],
        "proxyAddresses": [],
        "refreshTokensValidFromDateTime": "2018-02-27T19:46:09Z",
        "showInAddressList": null,
        "signInNames": [
            {
                "type": "emailAddress",
                "value": "[email protected]"
            },
            {
                "type": "userName",
                "value": "JDearing"
            }
        ],
        "sipProxyAddress": null,
        "state": null,
        "streetAddress": null,
        "surname": null,
        "telephoneNumber": null,
        "usageLocation": null,
        "userIdentities": [],
        "userPrincipalName": "__A_GUID__@__TENANT_NAME__.onmicrosoft.com",
        "userType": "Member"
    },

The only thing that changes there before and after finalizing the users registration is the refreshTokensValidFromDateTime field. You get even less fields with the Microsoft graph query:

https://graph.microsoft.com/v1.0/users?$filter=creationType eq 'LocalAccount'

And not even $select=* fixes that. To create a better user experience, how can I create a B2C user where the password I initially provide to the user will work with an MFA account without them having to click "forgot password".

Yes I'd also like the password I give the user to be of one time user. That's a separate matter though.

1
You can use, Azure AD Graph API to create users. I don't understand the issue here, can you please clarify? - spottedmahn
@spottedmahn The issue is the user cannot immediatly log in. If I log in it says the password is not valid. I have to perform a password reset, which also requires me to setup MFA. I'd like the user to enter the password I gave them, and be told its a valid password, and then be prompted to setup MFA. - Justin Dearing
Gotcha. The "B2B" part of your question threw me off. I tried running your script and I get: "Cannot convert 'System.Object[]' to the type 'System.Collections.IDictionary' required by parameter" on the $SignInNames object - spottedmahn
@spottedmahn I needed to wrap the two New-Object calls in paranthesis. Fixed above - Justin Dearing
I posted an answer, I don't think it solves your problem though. Hopefully, it helps drive the conversation though :) - spottedmahn

1 Answers

2
votes

I executed your script against my B2C tenant and I was able to create a user and sign-in w/o issue. I've tried the same script against local accounts configured for usernames and emails. No issue w/ that either.

I created the user via a local B2C admin account.

You need to use a B2C tenant administrator account that is local to the B2C tenant. These accounts look like this: [email protected].

Source

create b2c admin

Powershell Script

$AzureAdCred = Get-Credential
#enter local B2C admin credential in the popup

Connect-AzureAD -Credential $AzureAdCred

$UserName="blah6985"
$EmailAddress="[email protected]"
$Password="UEDsda;lad-8af:L;"

$SignInNames = @(
    (New-Object `
        Microsoft.Open.AzureAD.Model.SignInName `
        -Property @{Type = "userName"; Value = $UserName}),
    (New-Object `
        Microsoft.Open.AzureAD.Model.SignInName `
        -Property @{Type = "emailAddress"; Value = $EmailAddress})
)

$PasswordProfile = New-Object `
    -TypeName Microsoft.Open.AzureAD.Model.PasswordProfile `
    -Property @{ 
        'Password' = $Password;
        'ForceChangePasswordNextLogin' = $false;
    };

New-AzureADUser `
    -DisplayName $UserName.Replace('_', ' ') `
    -CreationType "LocalAccount" `
    -AccountEnabled $true `
    -PasswordProfile $PasswordProfile `
    -SignInNames $SignInNames