ASP.NET Core 5.0 : MVC, Razor Pages, Web API, EF Core, Blazor, Design Patterns, and more. Private online coaching for software developers. Click here for more details.

Authenticate users using Microsoft account in ASP.NET Core

At times you want to integrate external logins with your ASP.NET Core applications. External logins include Microsoft accounts, Google, Facebook, or Twitter. When you use external logins, the login details such as user name and password aren't stored in your local database. They are stored in some external store and you are required to "get in touch" with that external source to authenticate your website users. In this article you will learn to integrate Microsoft Account based login mechanism in your ASP.NET Core web app.

Before you create your ASP.NET Core project you need to create an App Registration in the Azure Portal. So, go to Azure Portal and search for App Registrations.

Click on New registration button and create a new App registration entry called My Te

Make sure to select the third radio button that allows you to sign in using Azure AD + Personal Microsoft Accounts. Also, enter the Redirect URI textbox with your ASP.NET Core web app's base URL appended with "/signin-microsoft". We haven't created a web app yet but since we know the default port number used by the development web server we can enter it in the above textbox. If you plan to use IIS Express as the development web server then you can first create a web app to know the port number OR modify the Redirect URI later on.

Complete the app registration by clicking the Register button at the bottom.

Next, go to the new created Azure app registration's overview page and note down its client ID.

Now go to Certificates and Secrets section and create a new Client Secret.

Note down this client secret carefully.

This completes the Azure portal related tasks.

Now create a new ASP.NET Core MVC application. You can either use empty project template or MVC project template but do not select any particular authentication scheme. We will do all the configuration ourselves in order to understand how it works.

Then add the NuGet package - Microsoft.AspNetCore.Authentication.MicrosoftAccount.

Now open appsettings.json file and store the Client ID and Client Secret noted earlier as shown below:

"Authentication": {
  "ClientId": "your_client_id",
  "ClientSecret": "your_client_secret"
}

Next, open the Startup class and add this code in the ConfigureServices() method:

public void ConfigureServices(IServiceCollection services)
{

    services.AddControllersWithViews();
    services.AddRazorPages();

    services.AddAuthentication(options =>
    {
        options.DefaultScheme = 
CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = 
MicrosoftAccountDefaults.AuthenticationScheme;
    }).AddCookie()
      .AddMicrosoftAccount(o =>
    {
        o.ClientId = Configuration
["Authentication:ClientId"];
        o.ClientSecret = Configuration
["Authentication:ClientSecret"];
    });
}

The above code uses AddAuthentication() method to set default authentication scheme to cookies and default challenge scheme to Microsoft account.

The code also calls AddCookie() method to enable authentication cookies. The AddMicrosoftAccount() method configures the properties for Microsoft Account. Here we set the ClientId and ClientSecret properties to their respective values from the configuration file.

Now add the following calls in the Configure() method:

...
app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
...
...

We wire authentication middleware and authorization middleware using UseAuthentication() and UseAuthorization() calls.

Let's quickly see the UI of the app before we actually go to the view markup and code.

When you run the app you will see this :

When you click the Sign In button, you will be shown Microsoft account's Sign In page.

Upon successfully signing in using your Microsoft account credentials you will be shown this:

This page shown that you have successfully signed in to the app. There is a link to an action protected using [Authorize] attribute. And there are two buttons - Sign Out and Sign Out Completely. Clicking on the first button logs you out of the current app whereas clicking on the second button logs you out of the Microsoft account itself.

Let's see the markup and code that makes the above discussed UI work.

Open Index.cshtml and write this code:

@{
    Layout = "";
}

@if (User.Identity.IsAuthenticated)
{
    <h1>You are signed in</h1>
    <h2><a asp-action="Privacy">
Go to protected page</a></h2>
    <form asp-controller="Home" 
asp-action="SignOut">
        <button type="submit" name="signOutType" 
value="app">Sign Out</button>
        <button type="submit" name="signOutType" 
value="all">Sign Out Completely</button>
    </form>
}
else
{
    <h1>You are not signed in</h1>
    <form asp-controller="Home" 
asp-action="SignIn">
        <button type="submit">
Sign In</button>
    </form>
}

Here, we first check whether a user is logged in or not using User.Identity.IsAuthenticated property.

If a user is signed in we display a message and render a hyperlink pointing to Privacy() action of HomeController. The Privacy() action is marked with [Authorize] attribute and hence requires authenticated user to run. The Sign Out button and Sign Out Completely button both submit to SignOut() action of HomeController. We have set name and value attributes of these <button> element. Inside the SignOut() action, these values will help us detect which button was clicked.

If a user is not signed in we display a message accordingly and also show Sign In button. The Sign In button submits to SignIn() action of HomeController.

Now that you know the UI of the app, let's discuss the SignIn(), SiignOut(), and Privacy() actions.

The SignIn() action is shown below:

public IActionResult SignIn()
{
    var props = new AuthenticationProperties();
    props.RedirectUri = "/Home/SignInSuccess";

    return Challenge(props);
}

Inside the SignIn() action we create a new AuthenticationProperties object. And we set the RedirectUri property to SignInSuccess() action of HomeController. When a user successfully signs in using a Microsoft account, we want out app to know that the login was successful. So, upon successful login we redirect the control to SignInSuccess() action.

Then we call Challenge() method of the Controller base class and pass the AuthenticationProperties object to it. The Challenge() method triggers your app's authentication scheme. Recollect that we have set the authentication scheme in the AddAuthentication() method earlier.

The SignInSuccess() action doesn't do much in this case, it simply redirects to the Index() action. But you can add some app specific processing here if required.

public IActionResult SignInSuccess()
{
    return RedirectToAction("Index");
}

The SignOut() action is shown below:

public IActionResult SignOut(string signOutType)
{
    if (signOutType == "app")
    {
        HttpContext.SignOutAsync().Wait();
    }
    if (signOutType == "all")
    {
        return Redirect("https://
login.microsoftonline.com/common/
oauth2/v2.0/logout");
    }
    return RedirectToAction("Index");
}

If the uses has clicked on the Sign Out button we call SignOutAsync() method of HttpContext. The SignOutAsync() method simple deletes the authentication cookie, it doesn't log the use out of the Microsoft Account as such.

If the user has clicked on the Sign Out Completely button we redirect the request to the specified URL. This URL triggers the Microsoft Account's log out process and you will be asked this:

And when you pick an account, you are logged out of it:

The Privacy() action is decorated with [Authorize] attribute like this:

[Authorize]
public IActionResult Privacy()
{
    return View();
}

Just for the sake of confirming the user's name you can write this in the Privacy.cshtml file:

@{
    Layout = "";
}


<h1>Welcome @User.Identity.Name</h1>

Run the application and check the complete sign-in and sign-out flow.

You can read more about external login providers in the official documentation here.

That's it for now! Keep coding!!


Bipin Joshi is an independent software consultant, trainer, author, yoga mentor, and meditation teacher. He has been programming, meditating, and teaching for 24+ years. He conducts instructor-led online training courses in ASP.NET family of technologies for individuals and small groups. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Ajapa Yoga to interested individuals. To know more about him click here.

Get connected : Facebook  Twitter  LinkedIn  YouTube

Posted On : 12 October 2020


Tags : ASP.NET ASP.NET Core MVC .NET Framework C# Visual Studio


Subscribe to our newsletter

Get monthly email updates about new articles, tutorials, code samples, and how-tos getting added to our knowledge base.

  

Receive Weekly Updates