

Create Azure B2C users with Microsoft Graph and ASP.NET Core | Software Engineer...
source link: https://damienbod.com/2022/03/11/create-azure-b2c-users-with-microsoft-graph-and-asp-net-core/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Create Azure B2C users with Microsoft Graph and ASP.NET Core
This article shows how to create different types of Azure B2C users using Microsoft Graph and ASP.NET Core. The users are created using application permissions in an Azure App registration.
Code https://github.com/damienbod/azureb2c-fed-azuread
The Microsoft.Identity.Web Nuget package is used to authenticate the administrator user that can create new Azure B2C users. An ASP.NET Core Razor page application is used to implement the Azure B2C user management and also to hold the sensitive data.
public
void
ConfigureServices(IServiceCollection services)
{
services.AddScoped<MsGraphService>();
services.AddTransient<IClaimsTransformation, MsGraphClaimsTransformation>();
services.AddHttpClient();
services.AddOptions();
services.AddMicrosoftIdentityWebAppAuthentication(Configuration,
"AzureAdB2C"
)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
The AzureAdB2C app settings configures the B2C client. An Azure B2C user flow is implemented for authentication. In this example, a signin or signup flow is implemented, although if creating your own user, maybe only a signin is required. The GraphApi configuration is used for the Microsoft Graph application client with uses the client credentials flow. A user secret was created to access the Azure App registration. This secret is stored in the user secrets for development and stored in Azure Key Vault for any deployments. You could use certificates as well but this offers no extra security unless using directly from a client host.
"AzureAdB2C"
: {
"ClientId"
:
"8cbb1bd3-c190-42d7-b44e-42b20499a8a1"
,
"Domain"
:
"b2cdamienbod.onmicrosoft.com"
,
"SignUpSignInPolicyId"
:
"B2C_1_signup_signin"
,
"TenantId"
:
"f611d805-cf72-446f-9a7f-68f2746e4724"
,
"CallbackPath"
:
"/signin-oidc"
,
"SignedOutCallbackPath "
:
"/signout-callback-oidc"
},
"GraphApi"
: {
"TenantId"
:
"f611d805-cf72-446f-9a7f-68f2746e4724"
,
"ClientId"
:
"1d171c13-236d-4c2b-ac10-0325be2cbc74"
,
"Scopes"
:
".default"
//"ClientSecret": "--in-user-settings--"
},
"AadIssuerDomain"
:
"damienbodhotmail.onmicrosoft.com"
,
The application User.ReadWrite.All permission is used to create the users. See the permissions in the Microsoft Graph docs.
The MsGraphService service implements the Microsoft Graph client to create Azure tenant users. Application permissions are used because we use Azure B2C. If authenticating using Azure AD, you could use delegated permissions. The ClientSecretCredential is used to get the Graph access token and client with the required permissions.
public
MsGraphService(IConfiguration configuration)
{
string
[] scopes = configuration.GetValue<
string
>(
"GraphApi:Scopes"
)?.Split(
' '
);
var
tenantId = configuration.GetValue<
string
>(
"GraphApi:TenantId"
);
// Values from app registration
var
clientId = configuration.GetValue<
string
>(
"GraphApi:ClientId"
);
var
clientSecret = configuration.GetValue<
string
>(
"GraphApi:ClientSecret"
);
_aadIssuerDomain = configuration.GetValue<
string
>(
"AadIssuerDomain"
);
_aadB2CIssuerDomain = configuration.GetValue<
string
>(
"AzureAdB2C:Domain"
);
var
options =
new
TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var
clientSecretCredential =
new
ClientSecretCredential(
tenantId, clientId, clientSecret, options);
_graphServiceClient =
new
GraphServiceClient(clientSecretCredential, scopes);
}
The CreateAzureB2CSameDomainUserAsync method creates a same domain Azure B2C user and also creates an initial password which needs to be updated after a first signin. The users UserPrincipalName email must match the Azure B2C domain and the users can only signin with the the password. MFA should be setup. This works really good but it is not a good idea to handle passwords from your users, if this can be avoided. You need to share this with the user in a secure way.
public async Task<(string Upn, string Password, string Id)>
CreateAzureB2CSameDomainUserAsync(UserModelB2CTenant userModel)
{
if(!userModel.UserPrincipalName.ToLower().EndsWith(_aadB2CIssuerDomain.ToLower()))
{
throw new ArgumentException("incorrect Email domain");
}
var password = GetEncodedRandomString();
var user = new User
{
AccountEnabled = true,
UserPrincipalName = userModel.UserPrincipalName,
DisplayName = userModel.DisplayName,
Surname = userModel.Surname,
GivenName = userModel.GivenName,
PreferredLanguage = userModel.PreferredLanguage,
MailNickname = userModel.DisplayName,
PasswordProfile = new PasswordProfile
{
ForceChangePasswordNextSignIn = true,
Password = password
}
};
await _graphServiceClient.Users
.Request()
.AddAsync(user);
return (user.UserPrincipalName, user.PasswordProfile.Password, user.Id);
}
The CreateFederatedUserWithPasswordAsync method creates an Azure B2C with any email address. This uses the SignInType federated, but uses a password and the user signs in directly to the Azure B2C. This password is not updated after a first signin. Again this is a bad idea because you need share the password with the user somehow and you as an admin should not know the user password. I would avoid creating users in this way and use a custom invitation flow, if you need this type of Azure B2C user.
public
async
Task<(
string
Upn,
string
Password,
string
Id)>
CreateFederatedUserWithPasswordAsync(UserModelB2CIdentity userModel)
{
// new user create, email does not matter unless you require to send mails
var
password = GetEncodedRandomString();
var
user =
new
User
{
DisplayName = userModel.DisplayName,
PreferredLanguage = userModel.PreferredLanguage,
Surname = userModel.Surname,
GivenName = userModel.GivenName,
OtherMails =
new
List<
string
> { userModel.Email },
Identities =
new
List<ObjectIdentity>()
{
new
ObjectIdentity
{
SignInType =
"federated"
,
Issuer = _aadB2CIssuerDomain,
IssuerAssignedId = userModel.Email
},
},
PasswordProfile =
new
PasswordProfile
{
Password = password,
ForceChangePasswordNextSignIn =
false
},
PasswordPolicies =
"DisablePasswordExpiration"
};
var
createdUser =
await
_graphServiceClient.Users
.Request()
.AddAsync(user);
return
(createdUser.UserPrincipalName, user.PasswordProfile.Password, createdUser.Id);
}
The CreateFederatedNoPasswordAsync method creates an Azure B2C federated user from a specific Azure AD domain which already exists and no password. The user can only signin using a federated signin to this tenant. No passwords are shared. This is really good way to onboard existing AAD users to an Azure B2C tenant. One disadvantage with this is that the email is not verified unlike implementing this using an invitation flow directly in the Azure AD tenant.
public
async
Task<
string
>
CreateFederatedNoPasswordAsync(UserModelB2CIdentity userModel)
{
// User must already exist in AAD
var
user =
new
User
{
DisplayName = userModel.DisplayName,
PreferredLanguage = userModel.PreferredLanguage,
Surname = userModel.Surname,
GivenName = userModel.GivenName,
OtherMails =
new
List<
string
> { userModel.Email },
Identities =
new
List<ObjectIdentity>()
{
new
ObjectIdentity
{
SignInType =
"federated"
,
Issuer = _aadIssuerDomain,
IssuerAssignedId = userModel.Email
},
}
};
var
createdUser =
await
_graphServiceClient.Users
.Request()
.AddAsync(user);
return
createdUser.UserPrincipalName;
}
When the application is started, you can signin as an IT admin and create new users as required. The Birthday can only be added if you have an SPO license. If the user exists in the AAD tenant, the user can signin using the federated identity provider. This could be improved by adding a search of the users in the target tenant and only allowing existing users.
Notes:
It is really easy to create users using Microsoft Graph but this is not always the best way, or a secure way of onboarding new users in an Azure B2C tenant. If local data is required, this can be really useful. Sharing passwords between an IT admin and a new user should be avoided if possible. The Microsoft Graph invite APIs do not work for Azure AD B2C, only Azure AD.
Links
https://docs.microsoft.com/en-us/aspnet/core/introduction-to-aspnet-core
Recommend
-
6
Microsoft Cloud Show is sponsored by: Nintex has made it fast and easy to put The Power of Process™ to wo...
-
11
In today’s Microsoft Graph Mailbag post, we cover Azure AD applications and users for testing Microsoft Graph queries in a development environment.
-
8
Azure AD to Microsoft Graph migration for Azure command line tools. Azure AD to Microsoft Graph migration for Azure command line tools. ...
-
6
@fkilcomminsFrank KilcomminsAPI Technical Evangelist SmartBear. 15+ years tech industry experience. Software engineering, architecture & ❤️ing APIs
-
11
Updates Public preview: Microsoft G...
-
5
Invite external users to Azure AD using Microsoft Graph and ASP.NET Core This post shows how to invite new Azure AD external guest users and assign the users to Azure AD groups using an ASP.NET Core APP Connector t...
-
5
Create an Azure App Registration with PowerShell and MS GRAPH API API Reference and Permissions Read the following DOCS for more Details
-
4
Azure DevOps Graph connectors for Microsoft Search Gloridel Morales
-
9
Sharing Microsoft Graph permissions and solution Azure App Registrations This article looks at using Microsoft Graph permissions in Azure App registrations and whether you should use Graph in specific Azure Ap...
-
10
Build a meetings app with Azure Communication Services, Microsoft Graph and Microsoft Teams – Part 2...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK