Jan
13
Written by:
Michael Washington
1/13/2019 4:55 PM

Server-side Blazor (also known as Razor Components) provides options for deeper integration between the ‘client side’ and ‘server side’ code because the ‘client side’ code is processed server-side. With server-side Blazor, we end up using less code, and things are a lot less complex because we can trust that the end-user was not able to alter or hack the ‘client side’ code.
If the ‘client side’ code says a user is who they say they are, we can trust them. Otherwise, we have to always make a ‘round trip’ to the server, before permitting operations or returning sensitive data. The ‘round trip’ is still being made (because the ‘client site’ code is being generated ‘server side’), but, our code structure is now cleaner and more streamlined.
In this example, we will authenticate a person using their Microsoft Azure account (either Personal or Work/School account). While most of the code will be in the client project, the client code is running server side so we can trust that the user was not able to alter the identity that is set for them at login.

The user will click the Login button to start the login process.

The user enters their Microsoft Azure account (either Personal or Work/School account), and clicks Next.

Next, they enter their password and click the Sign in button.

They will be directed back to the application and their first name will display.
They can click the Logout button to log out.
Create The Application

Open Visual Studio 2017.

Select File then New then Project.

Select ASP.NET Core Web Application.
Name the project BlazorAD.

Select Server-side Blazor.
Enable SSL

To use Azure Active Directory for logging users in, the application should run using SSL (https),
To enable this, double-click on the Properties node in the server project (BlazorAD.Server).

- Select the Debug tab
- Click Enable SSL
- Click the Copy button
- Paste the SSL URL in the App URL box (this will start the application in SSL mode when debugging)

Click the Save button, to save the changes.
Also, save the App URL, you will need it in a later step.
Create The App Registration

To log in Azure Active Directory users, you need a App ID.
Go to : https://portal.azure.com, log in, and click Azure Active Directory, then App registrations (Preview), then New registration.

- Enter a Name for the App
- Select: Accounts in any organizational directory
- Enter the App URL you saved earlier and add signin-oidc to the end (because this will be specified as the CallbackPath in the appsettings.json file we will add in a later step)
- Click Register

The Overview page will display.
Copy and save the Application (Client) ID.
You will need it later.

Click on the Authentication node, enable ID tokens, and click Save.
Add Nuget Packages

Return to Visual Studio.
In the Solution Explorer, right-click on the solution node and select Manage NuGet Packages for Solution.

Add a reference to:
Microsoft.AspNetCore.Authentication.AzureAD.UI (must be 2.1.1 or higher)
This NuGet package will install a series of assemblies that will provide all the code needed for authentication.
In addition, when properly configured, in the remaining steps, it will create a virtual controller that will provide the functionality to sign users in and out of Azure Active Directory.
This eliminates a lot of code that you would otherwise have to write yourself.
Configure the Authentication Pipeline

Add a appsettings.json file to the server project (BlazorAD.Server), using the following code:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/common",
"ClientId": "{{{ YOUR APP ID }}}",
"CallbackPath": "/signin-oidc"
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
Replace
{{{ YOUR APP ID }}} with the
Application (Client) ID you saved earlier.

In the server project (BlazorAD.Server), open the Startup.cs file.
Add the following using statements to the top of the file:
using Microsoft.AspNetCore.Authentication.AzureAD.UI;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using System.Net.Http;
using Microsoft.AspNetCore.Authentication;
using Microsoft.IdentityModel.Tokens;
using System.Threading.Tasks;
Add the following to the Startup class:
// To hold the values from the appsettings.json file
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
Add the following to the bottom of public void ConfigureServices(IServiceCollection services) method:
// ***********************************************
// For more info on:
// Microsoft.AspNetCore.Authentication.AzureAD.UI
// see:
// https://bit.ly/2Fv6Zxp
// This creates a 'virtual' controller
// called 'Account' in an Area called 'AzureAd' that allows the
// 'AzureAd/Account/SignIn' and 'AzureAd/Account/SignOut'
// links to work
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options));
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential
// cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
// This configures the 'middleware' pipeline
// This is where code to determine what happens
// when a person logs in is configured and processed
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
// Instead of using the default validation
// (validating against a single issuer value, as we do in
// line of business apps), we inject our own multitenant validation logic
ValidateIssuer = false,
// If the app is meant to be accessed by entire organizations,
// add your issuer validation logic here.
//IssuerValidator = (issuer, securityToken, validationParameters) => {
// if (myIssuerValidationLogic(issuer)) return issuer;
//}
};
options.Events = new OpenIdConnectEvents
{
OnTicketReceived = context =>
{
// If your authentication logic is based on users
// then add your logic here
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
context.Response.Redirect("/Error");
context.HandleResponse(); // Suppress the exception
return Task.CompletedTask;
},
OnSignedOutCallbackRedirect = context =>
{
// This is called when a user logs out
// redirect them back to the main page
context.Response.Redirect("/");
context.HandleResponse();
return Task.CompletedTask;
},
// If your application needs to do authenticate single users,
// add your user validation below.
//OnTokenValidated = context =>
//{
// return myUserValidationLogic(context.Ticket.Principal);
//}
};
});
services.AddMvc(options => { })
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
// From: https://github.com/aspnet/Blazor/issues/1554
// Adds HttpContextAccessor
// Used to determine if a user is logged in
// and what their username is
services.AddHttpContextAccessor();
services.AddScoped<HttpContextAccessor>();
// Required for HttpClient support in the Blazor Client project
services.AddHttpClient();
services.AddScoped<HttpClient>();
Add the following to the bottom of the public void Configure(IApplicationBuilder app, IHostingEnvironment env) method:
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseMvc(routes =>
{
// Allows Blazor Client project code to call Blazor
// Server project pages
routes.MapRoute(name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

Save the file.
Rebuild the Solution.
It should build without errors.
Create The Login / Logout Control

In the client project (BlazorAD.App), create a LoginControl.cshtml file using the following code:
@using System.Security.Claims
@using Microsoft.AspNetCore.Http
@using BlazorAD.App.Shared
@page "/login"
@inject IHttpContextAccessor _httpContextAccessor
@inject HttpClient Http
<!--
The Microsoft.AspNetCore.Authentication.AzureAD.UI
NuGet package creates a 'virtual' controller that
contains code that allows the
/Account/signin and /Account/signout
links to work
-->
@if (User.Identity.Name != null)
{
<b>You are logged in as: @GivenName</b>
<a class="ml-md-auto btn btn-primary"
href="/AzureAD/Account/SignOut?post_logout_redirect_uri=@RedirectUri"
target="_top">Logout</a>
}
else
{
<a class="ml-md-auto btn btn-primary"
href="/AzureAD/Account/SignIn?redirectUri=@RedirectUri"
target="_top">Login</a>
}
@functions {
private ClaimsPrincipal User;
private string RedirectUri;
private string GivenName;
protected override void OnInit()
{
base.OnInit();
try
{
// Set the user to determine if they are logged in
User = _httpContextAccessor.HttpContext.User;
// Try to get the GivenName
var givenName =
_httpContextAccessor.HttpContext.User
.FindFirst(ClaimTypes.GivenName);
if (givenName != null)
{
GivenName = givenName.Value;
}
else
{
GivenName = User.Identity.Name;
}
// Need to determine where we are to set the RedirectUri
RedirectUri =
_httpContextAccessor.HttpContext.Request.Host.Value;
}
catch { }
}
}
Consume the Login Control

Open the MainLayout.cshtml file, and change all of the code to the following:
@inherits BlazorLayoutComponent
<div class="sidebar">
<NavMenu />
</div>
<div class="main">
<div class="top-row px-4">
<!-- ******************************** -->
<LoginControl />
<!-- ******************************** -->
</div>
<div class="content px-4">
@Body
</div>
</div>

When you run the project, you can now log in using Azure Active Directory.
Links
Blazor.net
Authentication for serverside Blazor (How to use IHttpContextAccessor)
Blazor Security/Authorization
A Demonstration of Simple Server-side Blazor Cookie Authentication
active-directory-dotnet-webapp-openidconnect-v2
Quickstart: Add sign-in with Microsoft to an ASP.NET Core web app
Download
The project is available at http://lightswitchhelpwebsite.com/Downloads.aspx
You must have Visual Studio 2017 (or higher) installed to run the code.
4 comment(s) so far...
Re: Azure Active Directory Authentication in Server Side Blazor
Hey Michael, nice article. This may be a dumb question but how do you establish authorization? I didn't see anything about roles.
Thanks
By Dave Vorgang on
1/23/2019 10:36 AM
|
Re: Azure Active Directory Authentication in Server Side Blazor
@Dave Vorgang - You basically just call a method from the Microsoft.AspNetCore.Authentication.AzureAD.UI assembly, passing in your Azure ClientID and it handles the login for you. You can access any roles the user has in their account you created for them in Azure Active Directory. See: https://bit.ly/2Fv6Zxp for a full explanation of what the Microsoft.AspNetCore.Authentication.AzureAD.UI assembly is doing 'behind the scenes'
By Michael Washington on
1/23/2019 10:41 AM
|
Re: Azure Active Directory Authentication in Server Side Blazor
Hi Michael,I have been trying to follow this to add AzureAD authentication to my Razor Components project (ASP.NET Core 3.0 Preview 2).I am stuck on...
By Ondrej on
2/15/2019 9:21 AM
|
Re: Azure Active Directory Authentication in Server Side Blazor
@Ondrej - Sorry this example was for a previous version of Blazor than the one your are using. All I can suggest is to download the sample code from the download page on this site and compare that code to your own.
By Michael Washington on
2/15/2019 9:25 AM
|