Token based authentication and Identity framework in ASP.NET Core - Part 1
Setting up Identity Framework in ASP.NET Core application
In ASP.NET Core identity framework is introduced as a membership provider making user management, authentication and authorization. It is built on to Entity Framework Core ORM which allows you to be storage type independent. You can use Microsoft SQL Server, but you can also use PostgresSQL database as your storage.
Setting up the identity library project
Sample project for this article is available on GitHub as a public repository, s feel free to download it and use it https://github.com/dejanstojanovic/dotnetcore-token-authentication
Let's start with creating our identity library as a new .NET Core class library project.
As first thing we are going to do is to install nuget packages, so switch to text editor of the project and include the following packages
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>netcoreapp2.1</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.1.0" /> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.1.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.0" /> </ItemGroup> </Project>
Since this is library project, not an executable, we do not have to setup any dependency injection. Injection will be done from the caller project, ASP.NET Core application of Unit test project.
Declaring entities and database context
Identity core comes with IdentityUser class as a base entity class. It contains most of the properties for the user account record, but you can easily extend it with your custom properties. Just for the example purpose we are going to inherit IdentityUser class and extend it with couple of properties.
Our new ApplicationUser inherits IdentityUser and extends it with FirstName an LastName properties
using Microsoft.AspNetCore.Identity; using System; using System.ComponentModel.DataAnnotations; namespace Sample.Core.Identity.Data.Enities { public class ApplicationUser :IdentityUser { [Required] [MaxLength(200)] public String FirstName { get; set; } [Required] [MaxLength(250)] public String LastName { get; set; } } }
For our custom ApplicationUser entity we are going to need IdentityDbContext of ApplicationUser type
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Sample.Core.Identity.Data.Enities; namespace Sample.Core.Identity.Data.DbContexts { public class ApplicationUserDbContext: IdentityDbContext<ApplicationUser> { public ApplicationUserDbContext(DbContextOptions<ApplicationUserDbContext> options) : base(options) { } } }
We are only going to stay at the basic identity, so this would be all regarding the identity mechanism setup.
Identity context migrations from the Visual Studio IDE
We have identity setup, but we still do not have the database. Since we are not injecting any implementation for the actual storage we need to involve IDesignTimeDbContextFactory of out ApplicationUserDbContext.
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using Microsoft.Extensions.Configuration; using Sample.Core.Identity.Data.DbContexts; using System.IO; namespace Sample.Core.Identity.Data { public class ApplicationUserDbContextFactory : IDesignTimeDbContextFactory<ApplicationUserDbContext> { public ApplicationUserDbContext CreateDbContext(string[] args) { var dbContext = new ApplicationUserDbContext(new DbContextOptionsBuilder<ApplicationUserDbContext>().UseSqlServer( new ConfigurationBuilder() .AddJsonFile(Path.Combine(Directory.GetCurrentDirectory(), $"appsettings.json")) .Build() .GetConnectionString("DatabaseConnection") ).Options); dbContext.Database.Migrate(); return dbContext; } } }
Since we are going to read connection string from the configuration, we are going to need appsetting.json configuration file containing the connection string key
{ "ConnectionStrings": { "DatabaseConnection": "Data Source=.\\SQLEXPRESS;Initial Catalog=SampleIdentity;Integrated Security=SSPI;" } }
I am using my local Microsoft SQL Server Express instance, but depending on your storage choice you can pick any other database like PostgressSQL or even MySql.
Next step is to enable migrations and apply it to the database. You can either use PowerShell or user Visual Studio 2017 NuGet Package Manager console. Execute the following two commands for enabling and applying migrations to the target database
Add-Migration InitialCreate -Project Sample.Core.Identity.Data -Context ApplicationUserDbContext Update-Database -Project Sample.Core.Identity.Data -Context ApplicationUserDbContext
To make sure database is there with our custom user properties, connect to your Microsoft SQL Server instance and execute following query to get the AspNetUsers table structure
use SampleIdentity select t.[name] as 'Table', c.[name] as 'Column', d.[name] as 'Data Type', c.[is_nullable] as 'Is Nullable' from sys.schemas s inner join sys.tables t on s.schema_id = t.schema_id inner join sys.columns c on t.object_id = c.object_id inner join sys.types d on c.user_type_id = d.user_type_id where t.name='AspNetUsers'
You can see that our two custom columns FirstName and LastName are there and that makes our identity library setup complete. Next step is to build ASP.NET Core Identity Service as Web API project.
Check out the Token based authentication and Identity framework in ASP.NET Core - Part 2
References
- https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-2.1&tabs=visual-studio%2Caspnetcore2x
- https://docs.microsoft.com/en-us/ef/core/
- https://docs.microsoft.com/en-us/ef/#pivot=efcore
- https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity
- https://dejanstojanovic.net/aspnet/2018/june/token-based-authentication-in-aspnet-core-part-2/
- https://dejanstojanovic.net/aspnet/2018/june/token-based-authentication-in-aspnet-core-part-3/
Disclaimer
Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.
Comments for this article