Trong bài viết này, mình sẽ hướng dẫn cách tạo JWT token và cách validate JWT token
JWT là gì?
JSON Web Token (JWT) là 1 tiêu chuẩn mở (RFC 7519) định nghĩa cách thức truyền tin an toàn giữa các thành viên bằng 1 đối tượng JSON. Thông tin này có thể được xác thực và đánh dấu tin cậy nhờ vào “chữ ký” của nó. Phần chữ ký của JWT sẽ được mã hóa lại bằng HMAC hoặc RSA.
JSON Web Token bao gồm 3 phần, được ngăn cách nhau bởi dấu chấm (.):
- Header
- Payload
- Signature (chữ ký)
Tổng quát thì nó có dạng như sau:
xxxxx.yyyyy.zzzzz
Trong đó, bạn cần lưu ý: secret key và expire time. Đây là 2 thành phần quan trọng dùng để tạo và validate token
Header
Phần Header dùng để khai báo kiểu chữ ký và thuật toán mã hóa sẽ dùng cho cái token của chúng ta.
Payload (Claims)
Phần thứ 2 của token đó là Payload, nơi chứa các nội dung của thông tin (claim). Thông tin truyền đi có thể là mô tả của 1 thực thể (ví dụ như người dùng) hoặc cũng có thể là các thông tin bổ sung thêm cho phần Header. Nhìn chung, chúng được chia làm 3 loại: reserved, public và private.
Reserved: là những thông tin đã được quy định ở trong 1. IANA JSON Web Token Claims registry. Chúng bao gồm: Chú ý rằng các khóa của claim đều chỉ dài 3 ký tự vì mục đích giảm kích thước của Token
- iss (issuer): tổ chức phát hành token, vd: Nhatkyhoctap
- sub (subject): chủ đề của token
- aud (audience): đối tượng sử dụng token, vd: http://nhatkyhoctap.blogspot.com
- exp (expired time): thời điểm token sẽ hết hạn
- nbf (not before time): token sẽ chưa hợp lệ trước thời điểm này
- iat (issued at): thời điểm token được phát hành, tính theo UNIX time
- jti: JWT ID
Public: Khóa nên được quy định ở trong IANA JSON Web Token Registry hoặc là 1 URI có chứa không gian tên không bị trùng lặp.
Ví dụ:
“https://www.techmaster.vn/jwt_claims/is_admin”: true
Private: Phần thông tin thêm dùng để truyền qua giữa các máy thành viên.
Ví dụ:
{
"sub": "1234567890",
"name": "paduvi",
"admin": true
}
Ví dụ cho phần Payload:
{
“iss”: “techmaster”,
“exp”: 1426420800,
“https://www.techmaster.vn/jwt_claims/is_admin”: true,
“user”: “paduvi”,
“awesome”: true
}
Signature
Phần chữ ký được tạo bằng cách kết hợp 2 phần Header + Payload, rồi mã hóa nó lại bằng 1 giải thuật encode nào đó, càng phức tạp thì càng tốt, ví dụ như HMAC SHA-256
Tạo project Web API
Tạo project Web API, với option No Authentication
Bạn sẽ có 2 hàm chính:
- GenerateSecurityToken: Tạo ra token với issue và audience là localhost
- AddTokenAuthentication: Dùng để validate token
Mở file appsettings.json, thêm:
"JwtConfig": {
"secret": "PDv7DrqznYL6nv7DrqzjnQYO9JxIsWdcjnQYL6nu0f",
"expirationInMinutes": 30
}
Cài đặt 2 packages:
- System.IdentityModel.Tokens.Jwt: hỗ trợ tạo, serialize, và validate token
- Microsoft.IdentityModel.Tokens: Includes types that provide support for SecurityTokens, Cryptographic operations: Signing, Verifying Signatures, Encryption.
Tạo JwtService với hàm GenerateSecurityToken, mục đích là tạo token dùng để cung cấp cho client
public class JwtService
{
private readonly string _secret;
private readonly string _expDate;
public JwtService(IConfiguration config)
{
_secret = config.GetSection("JwtConfig").GetSection("secret").Value;
_expDate = config.GetSection("JwtConfig").GetSection("expirationInMinutes").Value;
}
public string GenerateSecurityToken(string email)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_secret);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Email, email)
}),
Expires = DateTime.UtcNow.AddMinutes(double.Parse(_expDate)),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
Audience = "https://nhatkyhoctap.blogspot.com",
Issuer = "Nhatkyhoctap"
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}
Expires: thời gian hết hạn của 1 token
Key: dùng để mã hóa, và thuật toán ở đây là Hash256
Audience: chỉ định audience (site) nào được phép sử dụng
Issuer: nơi phát hành, thường là tên Resource Server
Lưu ý: Các thông tin trên phải trùng khớp với thông tin được khai báo trong trong hàm validate token
Để sử dụng Autorize, bạn mở WeatherForecastController, thêm thuộc tính [Authorize]
Thực hiện request tới /WeatherForecast, bạn sẽ nhận được kết quả:
Để thực hiện việc validate token, bạn cần cài đặt thêm thư viện: Microsoft.AspNetCore.Authentication.JwtBearer
Và 1 middleware để validate token
public static class AuthenticationMiddleware
{
public static IServiceCollection AddTokenAuthentication(this IServiceCollection services, IConfiguration config)
{
var secret = config.GetSection("JwtConfig").GetSection("secret").Value;
var key = Encoding.ASCII.GetBytes(secret);
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = true,
ValidateAudience = true,
ValidIssuer = "Nhatkyhoctap",
ValidAudience = "https://nhatkyhoctap.blogspot.com"
};
});
return services;
}
}
Mở file startup.cs, bạn thêm
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddTokenAuthentication(Configuration);
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "AuthTest.API", Version = "v1" });
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "AuthTest.API v1"));
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Để lấy token, bạn tạo TokenController
[Route("api/[controller]")]
[ApiController]
public class TokenController : ControllerBase
{
private IConfiguration _config;
public TokenController(IConfiguration config)
{
_config = config;
}
[HttpGet]
public string GetRandomToken()
{
var jwt = new JwtService(_config);
var token = jwt.GenerateSecurityToken("fake@email.com");
return token;
}
}
Tham khảo
https://www.c-sharpcorner.com/article/implement-jwt-in-asp-net-core-3-1/
https://techmaster.vn/posts/33959/khai-niem-ve-json-web-token
Chúc các bạn thành công!
Nhận xét
Đăng nhận xét