Chuyển đến nội dung chính

Hướng dẫn cách tạo và validate JWT token

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 (.):

  1. Header
  2. Payload
  3. 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

Bài đăng phổ biến từ blog này

[ASP.NET MVC] Authentication và Authorize

Một trong những vấn đề bảo mật cơ bản nhất là đảm bảo những người dùng hợp lệ truy cập vào hệ thống. ASP.NET đưa ra 2 khái niệm: Authentication và Authorize Authentication xác nhận bạn là ai. Ví dụ: Bạn có thể đăng nhập vào hệ thống bằng username và password hoặc bằng ssh. Authorization xác nhận những gì bạn có thể làm. Ví dụ: Bạn được phép truy cập vào website, đăng thông tin lên diễn đàn nhưng bạn không được phép truy cập vào trang mod và admin.

ASP.NET MVC: Cơ bản về Validation

Validation (chứng thực) là một tính năng quan trọng trong ASP.NET MVC và được phát triển trong một thời gian dài. Validation vắng mặt trong phiên bản đầu tiên của asp.net mvc và thật khó để tích hợp 1 framework validation của một bên thứ 3 vì không có khả năng mở rộng. ASP.NET MVC2 đã hỗ trợ framework validation do Microsoft phát triển, tên là Data Annotations. Và trong phiên bản 3, framework validation đã hỗ trợ tốt hơn việc xác thực phía máy khách, và đây là một xu hướng của việc phát triển ứng dụng web ngày nay.

Tổng hợp một số kiến thức lập trình về Amibroker

Giới thiệu về Amibroker Amibroker theo developer Tomasz Janeczko được xây dựng dựa trên ngôn ngữ C. Vì vậy bộ code Amibroker Formula Language sử dụng có syntax khá tương đồng với C, ví dụ như câu lệnh #include để import hay cách gói các object, hàm trong các block {} và kết thúc câu lệnh bằng dấu “;”. AFL trong Amibroker là ngôn ngữ xử lý mảng (an array processing language). Nó hoạt động dựa trên các mảng (các dòng/vector) số liệu, khá giống với cách hoạt động của spreadsheet trên excel.