Web API Asp.Net Core + JSON Web Token + Angular 6 Web App - Part 1

Today, I am going to build a Web API project using Asp.Net Core and implement authentication with JWT Web Token. Furthermore, I will build a Web Application using Angular 6 which will have a couple of pages and a restricted area.
I know that there are lots of posts about it and it is a pretty simple project. Actually, this post is dedicated to my co-workers, VB.Net Developers, who are looking to get out from their comfort zone digging into new technologies. In part 1 of this article, I will focus on backend project. In part 2, let's build the frontend project.

That said, let's get started.

Steps:
1 - Creating the Web API project
2 - Configuring JWT
3 - Installing and configuring Swagger
4 - Installing and using Dapper
5 - Creating classes to authenticate users from an existing database

1 - Creating the Web API project
From Visual Studio, select "New Project". Select the Visual C# | ASP.NET Core Web Application

In the next dialog, select the API project type. Uncheck the Configure for HTTPS checkbox(for instance, our project will not be deployed using SSL).Click OK.

With just a couple of mouse clicks, the API is ready!!! If we run the application, we will get something like this...

By default, ValuesController has added automatically to the project. Feel free to remove it if you want.

So far so good! Let's configure JWT Web Token.

2 - Configuring JWT
To configure JWT in WebAPI .NET Core, we just need to modify Startup.cs file, which is a class that runs when the application starts.

Option 1 - The following configuration is pretty simple. There is no Issuer and Audience validation. Everything that we need is to check the token's expiration date and the secret key. By specifying a key, the token can be validated without any need for the issuing server.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = false,
            ValidateAudience = false,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MySecretKey010203"))
        };
    });
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

Line 3 - Registering JWT authentication middleware by calling AddAuthentication method
Line 12 - Bad practice - Do not hardcode your secret key. I would recommend keeping it in appsettings.json. Or, could just come from a certificate store instead of a file(best way!).

Option 2 - Validating Issuer, Audience and specifying the certificate location.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true, 
            ValidIssuer = "http://localhost", // could be a domain, server name, whatever...
            ValidateAudience = true,
            ValidAudiences = new List<string> // multiple audience
            {
                "http://localhost",
                "http://client11.mydomain.com",
                "http://client22.mydomain.com",
                "clientId_xxx",
                "clientId_yyz",
                "whatever"
            },
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new X509SecurityKey(new X509Certificate2("MySelfSignedCertificate.pfx", "password"))
 
        };
    });
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

In order to make our authentication middleware available, let's add the app.UseAuthentication() in the Configure method.

1
2
3
4
5
6
7
8
9
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    app.UseAuthentication();
    app.UseMvc();
}

It's done!!! With few steps, we get a Web API running with JSON Web Token authentication.

3 - Installing and configuring Swagger
Swagger is an open source project for generating useful documentation and help pages for Web API projects. Swashbuckle.AspNetCore is a package tools for documenting APIs built on ASP.NET Core. You can install it by executing the following command inside Package Manager Console.

PM> Install-Package Swashbuckle.AspNetCore

Now, let's add the Swagger generator in the Startup.ConfigureServices method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = false,
            ValidateAudience = false,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MySecretKey010203"))
        };
    });
    services.AddSwaggerGen(options =>
    {
        options.SwaggerDoc("v1",
            new Info
            {
                Title = "Demo JSON Web Token",
                Version = "v1",
                Description = "Web API Asp.Net Core + JSON Web Token + Angular 6 Web App",
                Contact = new Contact
                {
                    Name = "Alexandre Miranda",
                    Url = "http://alexandreomiranda.com"
                }
            });
    });
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

In the Startup.Configure method, let's enable the middleware for serving the generated JSON document and the Swagger UI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    app.UseAuthentication();
 
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "Web API V1");
    });
    app.UseMvc();
}

That's all. Run the application and access the URL: http://localhost:21018/swagger (maybe another port number...)

5 - Installing Dapper
Dapper is a micro ORM which helps to map the native query output to a domain class. To install it, execute the following command inside Package Manager Console.

PM> Install-Package Dapper

6 - Creating classes to authenticate users from an existing database
In order to make our project structure a little more organized, let's create the folders "Repository" and "Models". By way of example only, our project contains a simple structure and the Repository layer will be called directly from Controllers. A Service layer between both would be the best approach in a complex scenario.

Database

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CREATE TABLE [dbo].[Users](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[Username] [varchar](50) NOT NULL,
	[Password] [varchar](50) NOT NULL,
	[IsAdmin] [bit] NOT NULL,
	[Status] [int] NOT NULL,
 CONSTRAINT [PK_dbo.Users] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
 
INSERT INTO Users (Username,Password,IsAdmin,Status)
VALUES('admin','1234',1,1);
 
INSERT INTO Users (Username,Password,IsAdmin,Status)
VALUES('user','1234',0,1);

Add two new solution folders: "Models" and "Repositories". Under the Models folder, create a new class "User", which represents the Users table in the database

1
2
3
4
5
6
7
8
public class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public bool IsAdmin { get; set; }
    public int Status { get; set; }
}

Under the Repositories folder, create a new class "UserRepository".

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//add namespace
using Dapper;
 
public class UserRepository
{
    private IConfiguration _configuration;
    public UserRepository(IConfiguration configuration) => _configuration = configuration;
 
    public User Login(string username, string password)
    {
        using (SqlConnection conn = new SqlConnection(
            _configuration.GetConnectionString("WebApiJWT")))
        {
            var qry = "SELECT * FROM Users WHERE Username = @usr AND Password = @pwd AND Status = 1";
            return conn.QueryFirstOrDefault<User>(qry , new { usr = username, pwd = password });
        }
    }
}

Create a new controller - "AuthenticationController"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[Route("api/[controller]")]
[ApiController]
public class AuthenticationController : ControllerBase
{
    private UserRepository _userRepository;
    public AuthenticationController(UserRepository userRepository) => _userRepository = userRepository;
 
    [HttpPost("login")]
    [ProducesResponseType(200, Type = typeof(JwtSecurityTokenHandler))]
    [ProducesResponseType(400)]
    public IActionResult Login([FromBody] User userParam)
    {
        var user = _userRepository.Login(userParam.Username, userParam.Password);
 
        if (user == null)
            return BadRequest(new { message = "Username or password is incorrect" });
 
        var userRole = (user.IsAdmin) ? "admin" : "user";
 
        var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MySecretKey010203"));
        var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);
 
        var tokenOptions = new JwtSecurityToken(
            claims: new List<Claim> {
                new Claim(ClaimTypes.Name, user.Username),
                new Claim(ClaimTypes.Role, userRole)
            },
            expires: DateTime.Now.AddDays(2),
            signingCredentials: signinCredentials
        );
 
        var tokenString = new JwtSecurityTokenHandler().WriteToken(tokenOptions);
        return Ok(new { Token = tokenString });
 
    }
}

Lines 5 and 6: We are injecting UserRepository into AuthenticationController constructor. In this case, the framework takes on the responsibility of creating an instance of the dependency and disposing of it when it's no longer needed.
So, let's register this dependency in the service container. Change Startup.ConfigureServices method adding the following line:

1
services.AddTransient<UserRepository, UserRepository>();

This is the final project structure:

Final Step: Running and testing authentication controller
Run the application and execute a test using Swagger.

Access the URL: http://localhost:21018/swagger and expand "/api/Authentication/login" method. Click on button "Try it out".

Change JSON text and click on "Execute"

Received token:

That's all for now. In the next part, I will build a frontend application and consume the generated token by this API.

Project available on my Github.
Source Code - Github

See you!!!

AngularJS + Gulp Skeleton

Build automation for AngularJS projects is indispensable for anyone who works with this amazing and powerful framework. If you are planning to work on new projects using AngularJS, this post is for you. In this article, I am going to show you in a few and simple steps, how to structure a new AngularJS project using GULP.

Tools required:
NPM / Node.js
Any code editor - Visual Studio Code is always a great choice!!!

Step One
Under your project's folder, run the command: "npm init". Before creating the package.json file, this command will ask you a few questions, it's ok if you just press [enter] for all of them.

C:\dev\angularjs-gulp-skeleton>npm init

Step Two
Install AngularJS, Angular Route and Angular UI Bootstrap(optional). Angular UI Bootstrap requires Bootstrap CSS version 3.x or higher.
Font-awesome and JQuery will be also installed just to show you how to configure gulpfile.js when new libraries are installed.
Continue reading

Creativity vs Best Practices

As a software developer, finding the balance between creativity vs best practices is quite challenging. Definitely, it is something that we should practice writing every line of code without regarding the size or level of a project's complexity.

In my opinion, the complexity lies in our mind and the more creative you are, the more complicated your code become if you do not follow best practices. Being open-minded, practicing instant refactoring, as well as being creative, certainly will help you to find that balance and, furthermore, to increase a project's maintainability. Making it more efficient, cheaper and faster to add new features in the future.

Creativity is a great virtue and projects built following a non-standardized approach will challenge you to be twice more creative to maintain them. Creativity has no limits! I love that idea, however, maintainable projects require using a large number of rules and patterns. That is the point! Be hundred percent sure that you are writing a code implementing, at least, the SOLID design principles and, at the same time, being creative. SOLID principles are a collection of best practices to make software designs more understandable, flexible and maintainable. This topic is not part of the central idea of this article, there is a good reference on this article from Uncle Bob The Principles of OOD.
Continue reading

VB.Net WebApi OAuth Token Based Authentication + Angular Login Application - Part 2

After a long time studying to take IELTS exam, and it took me a while, let's continue our post about OAuth Token Based Authentication. In this post we are going to build the frontend, which will be built based on Angular - Angular website- and Bulma, a modern CSS framework based on Flexbox - Bulma website

Tools required:
Node.js - Download Node.js website
Angular CLI - A command line interface for Angular. It will be installed by npm, which is a package manager for Node.js.
Visual Studio Code - or another source code editor.

Before we start, check out my DEMO Login Page - user: admin / password: 123456
Continue reading

VB.Net WebApi OAuth Token Based Authentication + Angular Login Application - Part 1

Although I have focused my studies on Asp.Net/C# over the last three years, I have been working on a WebAPI project running VB.Net on backend and I would like to share with you, VB.Net developers, a token-based authentication solution using this verbose, effective and popular language.

What we’ll build?
In this series of articles, the backend will be built using WebAPI on top of OWIN and AngularJS as a client web application. Both projects, Backend and Frontend, will be available on my Github.
Source Code - Github
Continue reading

SQL Server – Getting Not Null Field Properties From a Table

The SQL query below is pretty simple and has helped me quite a bit. Maybe it could help you one day!
Particularly, I am using it to implement my validation classes from a existing database.

1
2
3
4
5
6
SELECT o.Name AS TABLE_NAME,
       c.Name AS Field_Name,
       c.is_nullable AS Allow_Null
FROM sys.columns c
     INNER JOIN sys.objects o ON o.object_id = c.object_id
WHERE o.Name = '<table_name>' AND c.is_nullable = 0

All fields with "NOT NULL" properties will be displayed
Continue reading

Working with Dapper

Dapper is a micro ORM created by StackOverflow. It is pretty simple to use and really fast. For this reasons, I have been using Dapper to retrieve the data from the database instead of use Entity Framework. By the way, EF has some powerfull features and I have just used it for database input. If you need performance to read... use Dapper not EF!!!
Continue reading

Cuide bem do seu domínio! Parte 4

Seguindo com a série de posts sobre TDD, vamos implementar a última regra de negócios do nosso projeto que valida a idade do aluno de acordo com a faixa etária para o curso no momento da matrícula. Darei sequência a partir do código fonte disponibilizado na parte 3 deste tutorial.

Passo 23 - Vamos começar criando um nova especificação para a entidade Matricula. Crie uma nova classe na pasta \Specifications\Matriculas\MatriculaFaixaEtariaPorCursoSpecification.cs Continue reading

Cuide bem do seu domínio! Parte 3

Seguindo com o projeto baseado no TDD, vamos continuar os testes restantes e finalizar a implementação das regras de negócio na camada de domínio.

Até aqui testamos apenas as especificações da entidade Aluno que eram: Ter idade entre 6 e 18 anos e CPF único na base.
Utilizamos Rhino Mock onde criamos um repositório falso simulando uma consulta de CPF existente e Specification Pattern com o pacote DomainValidation. Talvez não houvesse necessidade aplicar specification pattern para um projeto pequeno. A ideia é apenas mostrar como podemos implementá-lo para atender n regras de negócio de forma simples.

Continue reading