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