ASP. NET Core Learning JWT Authentication Authorization Details

  • 2021-11-14 05:20:04
  • OfStack

Overview

Authentication and authorization is the basic function of many systems. In the previous PC era, authentication and authorization were usually realized based on cookies-session. At that time, the number of users of the system was usually not very large, so this method also worked well. With the increasing number of software users, the system architecture also expanded vertically from before (increasing server performance)- > Scaling horizontally (increasing the number of servers)

Operation of cookies-session

Client submits user information- > The server identifies the user- > Server saves user information- > Returns the session-id client- > Client Saves session-id- > Take session-id with each request for cookies

This approach is also not non-scalable, for example, session replication/third-party saving session (database, Redis)

Noun parsing

Authentication: Identify whether the user is legal or not

Authorization: Give users permissions (which resources can be accessed)

Authentication: Authenticate whether the authority is legal

Jwt strengths and weaknesses

Advantage

Stateless

token stores all authentication information, the server does not need to save user authentication information, reducing the pressure on the server, and the server is easier to expand horizontally. Because of statelessness, it will lead to its biggest disadvantage and it is difficult to log out

2. Support cross-domain access

Cookie does not allow out-of-domain access, while token supports

3. Cross-language

Based on the standardized JSON Web Token (JWT), it does not depend on a specific language. For example, the generated pair of Token can be used in multiple languages (Net, Java, PHP...)

Disadvantage

1. Token effectiveness problem

It is very difficult to unregister the published Token in the background, and it is usually necessary to use the third-party storage (database/cache) to unregister, which will lose the biggest advantage of JWT

2. Bandwidth occupied

The length of Token (depending on the stored content) is larger than that of session_id, and each request consumes more bandwidth. token only stores necessary information to avoid token being too long

3. Renewal is required

cookies-session is usually the framework has implemented the renewal function, each visit to update the expiration time, JWT needs to be implemented by itself, reference OAuth2 refresh Token mechanism to refresh Token

4. Consuming more CPU

Each request requires two steps: decrypting the content and verifying the signature. Typically, time is exchanged for space

You can only decide which authentication scheme to use according to your own usage scenario, and none of them is universal and perfect

AspNetCore Integrated Jwt Authentication

1. Add a package


dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

2. Add configuration


"JwtOptions": {
 "Issuer": "https://localhost:5001",
 "Audience": "https://localhost:5001",
 "SecurityKey": "1G3l0yYGbOINId3A*ioEi4iyxR7$SPzm"
}

3. Jwt Bearer Extensions (Options)


public static AuthenticationBuilder AddJwtBearer(this IServiceCollection services, Action<JwtOptions> configureOptions)
{
 if (configureOptions == null) throw new ArgumentNullException(nameof(configureOptions));

 var jwtOptions = new JwtOptions()
 {
  Issuer = "Jwt Authentication",
  Audience = "Wilson Pan Web Api",
 };
 // set customs optoins
 configureOptions(jwtOptions);

 // update Options 
 services.PostConfigure<JwtOptions>(options =>
 {
  options.Issuer = jwtOptions.Issuer;
  options.Audience = jwtOptions.Audience;
  options.SecurityKey = jwtOptions.SecurityKey;
 });

 return services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
     .AddJwtBearer(options =>
     {
      options.TokenValidationParameters = new TokenValidationParameters()
      {
       ValidIssuer = jwtOptions.Issuer,
       ValidAudience = jwtOptions.Audience,
       ValidateIssuer = true,
       ValidateLifetime = true,
       ValidateIssuerSigningKey = true,
       IssuerSigningKey = jwtOptions.SymmetricSecurityKey
      };
     });

}

4. ConfigureServices


services.AddJwtBearer(options =>
{
 options.Issuer = Configuration.GetValue<string>("JwtOptions:Issuer");
 options.Audience = Configuration.GetValue<string>("JwtOptions:Audience");
 options.SecurityKey = Configuration.GetValue<string>("JwtOptions:SecurityKey");
});

5. Configure


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

6. add AuthorizeController


//define claim 
var claims = new Claim[]
{
  new Claim(ClaimTypes.Name, username),
  new Claim(ClaimTypes.Email, $"{username}@github.com"),
  new Claim(ClaimTypes.Role, username == "WilsonPan" ? "Admin" : "Reader"),
  new Claim(ClaimTypes.Hash, JwtHashHelper.GetHashString($"{username}:{password}:{System.DateTime.Now.Ticks}")),
};

//define JwtSecurityToken
var token = new JwtSecurityToken(
  issuer: _jwtOptions.Issuer,
  audience: _jwtOptions.Audience,
  claims: claims,
  expires: System.DateTime.Now.AddMinutes(5),
  signingCredentials: _jwtOptions.SigningCredentials
);

// generate token
var result = new JwtSecurityTokenHandler().WriteToken(token);

7. Contrller/Action Add Authentication Authorization


[ApiController]
[Authorize]
[Route("[controller]")]
public class ApiController : ControllerBase
{
  ...
}

[HttpPost]
[Authorize(Roles = "Admin")]
public IActionResult Post()
{
  return Ok();
}

Rest Client


dotnet run

1. Authentication interface


@host = https://localhost:5001

# @name token
POST {{host}}/Authorize HTTP/1.1
Content-Type: application/x-www-form-urlencoded

#username=Wilson&password=123456
# admin 
username=WilsonPan&password=123456

2. Authorization interface is required


### required authorize
GET {{host}}/api HTTP/1.1
Authorization: Bearer {{token.response.body.*}}

3. Administrator role interface is required


"JwtOptions": {
 "Issuer": "https://localhost:5001",
 "Audience": "https://localhost:5001",
 "SecurityKey": "1G3l0yYGbOINId3A*ioEi4iyxR7$SPzm"
}
0

Sample code

Summarize


Related articles: