> mobileapp Strategy - From Idea to Mobile App RealityVinova Our team will brainstorm with you on where to begin, where to go, and how to get you there. Whether you have a spark of an idea or an existing app – we can help. Getting your mobile strategy right is what our unique services are all about. We’ll wrestle with business challenges, discover new opportunities that will help you define and refine your product ideas into mobile app reality.

Create Azure B2C users with Microsoft Graph and ASP.NET Core

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": {
    "Instance": "https://b2cdamienbod.b2clogin.com",
    "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
	};

	// https://docs.microsoft.com/dotnet/api/azure.identity.clientsecretcredential
	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

https://docs.microsoft.com/en-us/graph/api/user-post-users?view=graph-rest-1.0&tabs=csharp

This content was originally published here.

Malcare WordPress Security

web design services singapore,singapore web development,design firms in singapore,mobile app developer singapore,graphic designer in singapore,website design singapore,website developer singapore,website development singapore,singapore app developer,developers in singapore,app development singapore,mobile app development singapore,ios developer singapore,mobile developer singapore,mobile game developer singapore,ios app development singapore,web application singapore,singapore mobile app developer,singapore website design,singapore mobile application developer,web designer singapore,app developer singapore,developer in singapore,web development company singapore,mobile application developer singapore,mobile apps development singapore,design agency singapore,mobile apps singapore,singapore web design services,web design company singapore,mobile application development singapore,ruby on rails developer singapore,website designer singapore,web development singapore,web design singapore,singapore web design,android developer singapore