Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

ASP.NET Core - Authentication UI Installation

0.00/5 (No votes)
9 Nov 2018 1  
Tutorial about how to add authentication functionalities to your existing ASP.NET Core project using Microsoft.AspNetCore.Identity.UI package

Introduction

In this article, I want to show you how to add authentication functionalities to your existing ASP.NET Core project using Microsoft.AspNetCore.Identity.UI NuGet package. The package can help us a lot, but we need to understand what the package have and how to hook it up to your application.

In this tutorial, starting from the template of ASP.NET Core Web Application, you will see how authentication UI and identity persistence are easily installed into an existing web application. Your web application will have the following features:

  • Register a new user
  • Change user's password
  • Login to application
  • Logout from application

Requirements

  • .NET Core SDK 2.1 (2.1.403)
  • PostgreSQL 10.3

What is written in this article is also confirmed to work with .NET Core 2.1.302.

PostgreSQL is to be the storage for identity persistence.

Installation Steps

  1. Authentication and Identity UI Configuration
  2. Identity Persistence Implementation
  3. Page Transitions Implementation

1. Authentication and Identity UI Configuration

Create a project with ASP.NET Core Web App template and run it. You can see the web page that was generate by the template. As you can see, there is no link for Log in or Register.

Before you go to the next, let's update Microsoft.AspNetCore.App package to the latest one. In my case, the generated project had 2.1.1, and I updated to 2.1.5.

After updating the package, you could get an build error NETSDK1061. Don't worry about it. It's nothing serious. You just need to edit csproj file a bit. If your project file has the lines that look like below, then it is the cause.

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

Add Version attribute to the node as follows, then the error will disappear.

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.5" />
  </ItemGroup>

If you are using Visual Studio 2017, you can see the following two packages under Microsoft.AspNetCore.App package in the NuGet package tree. Those are the packages we are going to utilize.

  • Microsoft.AspNetCore.Authentication
  • Microsoft.AspNetCore.Identity.UI

In order to hook up those packages, you need to configure your web application. The packages provides extension methods with which we can finish the configuration easily.

Add the following code to Configure method in Startup.cs,

app.UseAuthentication();

and the code below in ConfigureServices method.

services.AddDefaultIdentity<IdentityUser>();

Now your web application is configured so that the requests to the following URLs are routed to the code in the Identity UI package.

  • /Identity/Account/Register
  • /Identity/Account/Login
  • /Identity/Account/Manage
  • /Identity/Account/Logout

However, those still do not work because the views of those require a partial view, which is located at /Views/Shared/ and named _LoginPartial.cshtml.

Create the partial view file. You don't have to have any content in it, so let's just leave it as an empty file for now.

2. Identity Persistence Implementation

Before you can see contents at the URLs above, you need to finish implementation of identity persistence. The code in the package requires a storage to persistent the authentication information.

Firstly, have a database, and secondly, configure your application to use Entity Framework Core. Then, you can generate the required tables by Entity Framework Core tools.

Create Database

If you already have some database that you can use for it, skip this section. If not, follow the instruction below to quickly make an empty PostgreSQL database in your local machine.

Install PoinstgreSQL server if you don't have it, and create a new directory anywhere for your database, while giving access to the user of the server process. After that, create a text file with the SQL script below, and name it CreateDb.sql.

create role :name with LOGIN PASSWORD :pw;
create tablespace :name location :dir;
set default_tablespace = :name;
create database :name owner :name encoding 'UTF-8' template template0;

Then, run it by psql with the command below, while replacing $DB_DIR with the database directory path that you right created. The script creates a database user and a new database, where both name are the same, sampledb.

psql -U postgres -f CreateDb.sql -v dir="'$DB_DIR'" -v name=sampledb -v pw="'sample'"

If you want to delete and recreate the database later, use the sceript and the command below.

\c postgres
drop database if exists :name;
drop tablespace if exists :name;
drop role if exists :name;
psql -U postgres -f DeleteDb.sql -v name=sampledb

You don't need to delete and create the database directory again. After running it,  run the database creation script again.

Configure ASP.NET Core for Entity Framework Core

Now, there is a database ready to connect. Let's configure ASP.NET Core to connect the database via Entity Framework Core. The following instruction assumes that you use PostgreSQL database.

Firstly, create a database context class for the authentication information. You can directly use Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityDbContext instead, but it is possible only when Entity Framework is used only for the sake of IdentityDbContext in your application.

namespace IdentityUiSample.Models
{
    public class AppIdentityDbContext : IdentityDbContext
    {
        public AppIdentityDbContext(DbContextOptions<AppIdentityDbContext> options) : base(options) { }
    }
}

Next, add two NuGet packages below, and add the following lines into Startup.ConfigureServices method.

  • Npgsql.EntityFrameworkCore.PostgreSQL
  • Npgsql.EntityFrameworkCore.PostgreSQL.Design
services.AddDbContext<AppIdentityDbContext>(options =>
    options.UseNpgsql(Configuration.GetConnectionString("SampleDB")));

Then, add SampleDB connection string to appsettings.json that looks like below.

{
  "ConnectionStrings":  {
    "SampleDB": "Server=localhost;Database=sampledb;User Id=sampledb;Password=sample;"
  }
}

Finally, add the call for AddEntityFrameworkStores method with AppIdentityDbContext class after the code you added previously.

services
    .AddDefaultIdentity<IdentityUser>()
    .AddEntityFrameworkStores<AppIdentityDbContext>();

Create Tables by Entity Framework Core Tools

Now, you have a database and code that uses Entity Framework Core. You can finally use Entity Framework Core tools to generate database tables.

At the project root directory, run the two commands below in order. Make sure that your web application is not running before runing those. Otherwise, those tools fail. It is because the tools need to run your application.

The value for command line switch -c in both of those commands is the full name of your database context. Please replace the name so as to match your database context type. If your application only have a single database context, then you can also omit the switch.

dotnet ef migrations add first -c IdentityUiSample.Models.AppIdentityDbContext -v
dotnet ef database update -c IdentityUiSample.Models.AppIdentityDbContext -v

After those commands succeed, you can find a series of new tables and Migrations directory made under the project root with generated files in it.

When you make some changes in the databse context class and you need to run the tools again, run those two commands again but change first in the first command to any other key word.

Okay, now you should be able to see the login page. Run the web application and navigate to the path /Identity/Account/Register on browser. Try register an account and login with it at /Identity/Account/Login.

3. Page Transitions Implementation

As you may notice, you haven't got Login link anywhere in your application. So, the last part will add the page transitions in order to integrate the authentication functionalities to your application.

The partial view _LoginPartial.cshtml, which you created, is rendered in the navigation bar, it is thus a good place to add the links to the authentication related pages. Formerly, you created it as an empty file. Now, add the following code in it.

@using Microsoft.AspNetCore.Identity
@using Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
@model dynamic
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager
<ul class="nav navbar-nav navbar-right">
    @if (SignInManager.IsSignedIn(User))
    {
        <li><a href="/Identity/Account/Manage">@UserManager.GetUserName(User)</a></li>
        <li>
            <form asp-area="Identity" asp-page="/Account/Logout" method="post">
                @Html.Hidden("returnUrl", "/")
                <input type="submit" value="Logout" class="btn btn-link navbar-btn navbar-link" />
            </form>
        </li>
    }
    else
    {
        RegisterModel register = Model as RegisterModel;
        LoginModel login = Model as LoginModel;
        @if (register == null)
        {
            <li><a href="/Identity/Account/Register">Register</a></li>
        }
        @if (login == null)
        {
            <li><a href="/Identity/Account/Login">Login</a></li>
        }
    }
</ul>

Acquisition of User Information in Razor View

The lines starting with @inject directive let you introduce the login information in razor view code. Then, you can get the current login user name by @UserManager.GetUserName(User).

Model of _LoginPartial.cshtml

The reason why receiving model as dynamic by @model dynamic, is that the partial view is rendered not only in Login page but also other pages and in each, different model type is passed. By defining model as dynamic, the view can receive model instance in any case.

Logout Link

The link to /Identity/Account/Logout is coded as form with asp-area and asp-page attribute. This is because it requires POST request with anti-forgery token. Using the asp- attributes is not neccesary but just makes the code a little bit simpler. The following code is an equivalent, where you explicitly see the code for the anti-forgery token.

            <form action="/Identity/Account/Logout" method="post">
                @Html.AntiForgeryToken()
                @Html.Hidden("returnUrl", "/")
                <input type="submit" value="Logout" class="btn btn-link navbar-btn navbar-link" />
            </form>

The form data returnUrl is optional, by the way. It just enables to skip Logout page and redirects to a path.

Install Partial View to _Layout.cshtml

At the very end, go to /Views/Shared/_Layout.cshtml, which is the layout used in your application by default. Search by "navbar-nav" and find the lines like below, and then, add the one line that is shown in itallic text.

<div class="navbar-collapse collapse">
    <ul class="nav navbar-nav">
        <li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
        <li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
        <li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
    </ul>
    <partial name="~/Views/Shared/_LoginPartial.cshtml" />
</div>

All done!

Now, try login and logout. From the link on the user name, you can go to account management page.

Next Steps

Some functionalities in the Identity UI has not been fully configured yet. For example, ForgotPassword page does not actually send emails. For further configurations, there are instructions in Microsoft website. I'm sure, after you go through this tutorial, it is not difficult to follow the instructions there.

Sample

You can get the sample project of the tutorial from the link blow. However, be aware that you still need to implement identity persistence by yourself in order to run it.

Download sample

History

  • 2018-11-10: Published the first edit.

 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here