A step by step guide to creating an ASP.NET hosted Blazor WASM client that uses Azure Active Directory to authenticate.
NOTE: You can read my blog covering this Here - it is almost identical to this document, except it has some additional comments explaining some of the steps.
Allows absolutely anyone to use your app as long as they have authenticated using Azure Active Directory. The user doesn't need to be in your directory, just some directory.
Note that this doesn't restrict who can access your application, nor what they can do once they've signed in. It just ensures you know the person using your application has gone through the necessary sign-in process on Azure Active Directory.
- Sign into https://portal.azure.com
- Select your subscription
- In the menu on the left hand side (Left menu) select
Resource providers
- Click
Microsoft.Azure.ActiveDirectory
- If its status is not
Registered
, clickRegister
at the top of the page
- From the Azure home page click
Create a resource
- Search for
Azure Active Directory
- Find the
Azure Active Directory
icon (NOT B2C) - Click the
Create
link at the bottom of the item - Click
Azure Active Directory
in the popup menu - For
Tenant type
selectAzure Active Directory
(NOT B2C) - Click
Next
- Enter an
Organization name
andInitial domain name
(e.g.MyOrg
andMyOrgInitialDomain
) - Select your
Location
- Click
Review + create
- Click
Create
- Click your user account icon at the top-right of the page
- Click
Switch directory
in the popup menu - Refresh your browser if your new tenant is not listed
- Click
Switch
next to your new directory in the list
- Click the three horizontal lines (burger menu) at the top-left of the page
- Select
Azure Active Directory
from the popup menu - In the left-menu, click
App registrations
- Click
New registration
at the top of the page - Give it a name (e.g. "MyApp")
- For
Supported account types
selectAccounts in any organizational directory (Any Azure AD directory - Multitenant)
- Under
Redirect URI
selectSingle-page application (SPA)
for the platform - For the URI enter
https://localhost:6510/authentication/login-callback
- In the left menu, click
Overview
- Make a note of the value of
Application (client) ID
- In the left menu, click
Authentication
- Under
Single-page application
clickAdd URI
- Enter the login-callback URI of your app (e.g.
https://ibm.com/authentication/login-callback
) - Click
Save
- Click the burger menu at the top-left of the page
- Select
Azure Active Directory
- In the left menu, click
App registrations
- Click your application in the list
- In the left menu, click
Expose an API
- At the top of the page, find
Application ID URI
and clickSet
- It will default to
api://{Application (client) ID}
, this ID is acceptable (NOTE:{}
denotes the value, e.g.d581756b-53b0-4957-820a-d6aa43fd69de
) - Click
Save
- Click
Add a scope
- For
Scope name
enter a name you wish to use to identify the scope (e.g.access_as_user
) - For
Who can consent
selectAdmins and users
- For
Admin consent display name enter
Read user's profile information` - For
Admin consent description
enterAllows the application to read the user's profile information
- For
User consent display name
enterRead your profile information
- For
User consent description
enterAllows the application to read your profile information
- Ensure
Enabled
is selected - Click
Add scope
- In left menu, click
API permissions
- Click
Add a permission
- Click the
[My APIs]
tab at the top of the popup menu - Click your application in the list of items
- In the
Permissions
section ensureaccess_as_user
is checked - Click `Add permissions
- In the same
API permissions
page, clickAdd a permission
- Select the
Microsoft Graph
item at the top of the popup menu - Click the
Delegated permissions
item in the popup menu - Ensure
email
andopenid
are both checked - Click 'Add permissions`
When you've finished the above steps, click the Grant admin consent for {Your organisation name} and then click
Yes`. Remember this step if you add any additional permissions
in future.
- Create a new ASP.NET hosted Blazor WASM application in Visual Studio
- IMPORTANT: For
Authentication type
selectMicrosoft identity platform
- The
Required components
wizard will appear and try to connect to your AAD registered app. This will also add items to AAD that we don't want (another app registration) - Click
Cancel
Edit Properties/launchSettings.json
in both the client and
server app, and set the applicationUrl
to https://localhost:6510
- Edit
wwwroot/appsettings.json
- Replace the contents with the following
{
"AzureAd": {
"ClientId": "{Application (client) ID}",
"Authority": "https://login.microsoftonline.com/organizations"
},
"ServerApi": {
"Scopes": "api://{Application (client) ID}/access_as_user"
}
}
- Replace
{Application (client) ID}
with the GUID you noted earlier
- Edit
Program.cs
- Change the
AddMsalAuthentication
section so scopes are read from the config file
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
string? scopes =
builder.Configuration!.GetSection("ServerApi")["Scopes"]
?? throw new InvalidOperationException("ServerApi::Scopes is missing from appsettings.json");
options.ProviderOptions.DefaultAccessTokenScopes.Add(scopes);
// Uncomment the next line if you have problems with a pop-up sign-in window
// options.ProviderOptions.LoginMode = "redirect";
});
- Edit
appsettings.json
- Replace the
AzureAd
section with the following
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "organizations",
"ClientId": "{Application (client) ID}",
"Scopes": "api://{Application (client) ID}/access_as_user"
}
- Replace
{Application (client) ID}
with the GUID you noted earlier
- Edit
Program.cs
- Replace
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
with
builder.Services.AddMicrosoftIdentityWebApiAuthentication(builder.Configuration);
builder.Services.AddAuthorization();
- Edit
Program.cs
- Replace
builder.Services.AddControllersWithViews();
with
builder.Services.AddControllers();
- Edit
Program.cs
- Remove
builder.Services.AddRazorPages();
- Remove
app.UseRazorPages();
This step is only required until I work out why the user's scopes are not being passed to the server.
- Edit
WeatherForecastController.cs
- Comment out the line with the
[RequiredScope]
attribute on it