Problem
How to implement Azure AD authentication in ASP.NET Core 2.0
Solution
In previous posts, we have seen how to secure our applications using:
- Custom login/logout pages using Cookie Authentication.
- JWT to secure web services.
- NET Identity to simplify identity and access management.
- IdentityServer4 to delegate identity and access management to a dedicated application.
In this and the next post, I’ll demonstrate how to use Azure AD to delegate identity and access management to Azure, simplifying our application.
Configure Azure AD
Create Azure subscription (start for free, gives you credit to play).
Create new resource and search for ‘Azure active directory’,
Create new instance
Enter details, including the unique ‘initial domain name’, this will become the Tenant Name that will be used in your application; e.g. below the tenant name will be fiverad.onmicrosoft.com,
Once directory is created, we need to register our application,
Enter details for your application, including the URL to your application home/sign-in page,
Once the application is created, you’ll see ‘Application ID’ in the list. This will be used in our application later as ‘Client ID’,
Click on application and ‘Reply URLs, enter URL where Azure AD will redirect user after authentication (https://localhost:44308/security/signin-callback),
Next we’ll create a user in Azure AD,
Note that username is based on our directory’s domain name i.e. @fiverad.onmicrosoft.com. Also, make a note of the temporary password, you’ll be required to change it on the first login.
So far you have,
- Created Azure AD
- Registered your application
- Added a user
Next, we’ll setup our application and use Azure AD to authenticate users.
Configure Application
Create an empty project and update Startup to configure services and middleware for MVC and Authentication:
- public class Startup
- {
- private readonly string TenantName = "";
- private readonly string ClientId = "";
-
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddAuthentication(options =>
- {
- options.DefaultAuthenticateScheme =
- CookieAuthenticationDefaults.AuthenticationScheme;
- options.DefaultSignInScheme =
- CookieAuthenticationDefaults.AuthenticationScheme;
- options.DefaultChallengeScheme =
- OpenIdConnectDefaults.AuthenticationScheme;
- }).AddOpenIdConnect(options =>
- {
- options.Authority = "https://login.microsoftonline.com/" +
- this.TenantName;
- options.ClientId = this.ClientId;
- options.ResponseType = OpenIdConnectResponseType.IdToken;
- options.CallbackPath = "/security/signin-callback";
- options.SignedOutRedirectUri = "https://localhost:44308/";
- }).AddCookie();
-
- services.AddMvc();
- }
-
- public void Configure(IApplicationBuilder app, IHostingEnvironment env)
- {
- app.UseAuthentication();
- app.UseMvcWithDefaultRoute();
- }
- }
Here we are setting up Open ID Connect authentication middleware services with:
- Authority
Path to the Azure AD tenant that we’ve setup as authentication server
- ClientId
Application identifier that Azure AD provides for our application.
- ResponseType
The value that determines authorization flow used and parameters returned from the server. We are interested only in authorization token for now.
- CallbackPath
The path where a server will redirect after authentication. We don’t need to create this in our application, the middleware will handle this.
- SignedOutRedirectUri
The path where the server will redirect after signing out. This is the path to our application home page, for instance.
Also when configuring authentication middleware, we’ve specified Open ID Connect as challenge scheme. This is the middleware ASP.NET Core will use for users who have not been signed in.
Once signed in, we want to store their identity in a cookie, instead of redirecting to an authentication server for every request. For this reason we’ve added cookie authentication middleware and are using that as default sign-in scheme. If the cookie is missing, users will be ‘challenged’ for their identity.
Add a controller to implement login/logout actions,
- public class SecurityController : Controller
- {
- public IActionResult Login()
- {
- return Challenge(new AuthenticationProperties { RedirectUri = "/" });
- }
-
- [HttpPost]
- public async Task Logout()
- {
- await HttpContext.SignOutAsync(
- CookieAuthenticationDefaults.AuthenticationScheme);
- await HttpContext.SignOutAsync(
- OpenIdConnectDefaults.AuthenticationScheme);
- }
- }
When logging out it is important to sign-out from authentication server (Azure AD) and also remove the cookie by signing out from cookie authentication scheme.
Secure controllers (or their actions) using [Authorize] attribute
- [Authorize]
- public class HomeController : Controller
- {
- public IActionResult Index()
- {
- return View();
- }
- }
Run the application and you’ll be redirected to Azure for authentication.
Source Code
GitHub