JSON Web Token Introduction - jwt.io

هنرجع تاني للـ Security Module آخر حاجة عملناها هي الـ Login and Register Endpoints

وكنا واقفين عند جزئية اننا عايزين نعمل Generate للـ Token باستخدام الـ JWT


فكرة الـ Token

الـ Token: عبارة عن Encrypted String -بناخد مجموعة من الـ Inputs ونعديها على Security Algorithm بيبدأ يعملها شوية Equations و Encryption وكدا- وبيطلعلي الـ String بتاعتي وبنقول عليها انها الهوية Identity فلو مفيش Token وعايز ادخل على Netflix واتفرج على فيلم فيقولي انت مين اقوله انا كذا واليوزر بتاعي كذا والباسوورد كذا وبعد ما اخلص الفيلم اعوز اتفرج على فيلم تاني فيسأل انت مين فأبعتله نفس اليوزر والباسوورد وكل شوية كدا فدا مش منطقي انما المنطق بيقول اني اول مرة أعمل Login فالـ Server side يعملي Token ويرجعه للـ End-user اللي هو انا وانا افضل محتفظ بيه وكل مرة اعوز اعمل Request لـ Netflix ابعت الـ Token دا في الـ Request فالـ Request يعدي كل مرة

احنا بنعمل دلوقتي الـ API وهنعمل Run لـ Project الـ Angular فالمفروض ان الـ Front-end developer فهو بيعمل حاجة اسمها Interceptor فالبتاع دا بيحط مناخيرة في كل حاجة (متدخل) فالفرونت اند ديفولوبر بيعمل Implement للـ Interceptor دا اللي هو بيمسك كل Request رايح يكلم كل Endpoint من الـ API والـ Endpoint لازم يكون Authorize عشان يكلمها فالفرونت اند بيخلي الـ Interceptor يعمل Intercept ويمسك الـ Request يلزق فيه الـ Token بشكل اوتوماتيك فأي Request هيحط فيه الـ Token


لما الـ Front-end عمل Consume للـ Login ودخل رجعتله الـ Token

وهو بيروح يخزنه في الـ Local storage أو أي حاجة

النهاردة هنستخدم الـ JWT package

JWT package

JSON Web Token: Encrypted String generated from JSON

JSON Web Tokens - jwt.io

بنختار الـ Security Algorithm

التشفير وفك التشفير ببساطة (ABC Encryption)

  1. البيانات الأصلية (Plaintext):
    البيانات التي تريد إرسالها، مثل:
    1, 2, 3
  2. التشفير (Encryption):
    استخدام معادلة معينة لتحويل البيانات إلى شكل مشفر، مثل:
    إضافة 10 لكل رقم
    الناتج: 11, 12, 13
  3. الإرسال (Transmission):
    يتم إرسال البيانات المشفرة بأمان إلى المستقبل.
  4. فك التشفير (Decryption):
    لدى المستقبل معادلة عكسية لفك التشفير، مثل:
    طرح 10 من كل رقم
    فيتم تحويلها إلى الشكل الأصلي: 1, 2, 3

الخلاصة:

التشفير هو عملية تعديل البيانات باستخدام معادلة، بينما فك التشفير يعيد البيانات إلى شكلها الأصلي باستخدام معادلة معاكسة.

Why we use Token

بستخدم الـ Token عشان حاجتين:

  • الـ Authentication و Authorization
  • الـ Information Exchange: بنعمل الـ Token من خلال شوية Data فلما أبعت الـ Token للـ Front-end ببعت معلومة سرية لحاجة معينة معاه مثلًا باسوورد أو حاجة، فالـ Front-end يعمله Decoding ويطلع المعلومات دي

الـ Token بيتكون من ايه

بيتكون من 3 حاجات:

  • الـ Header: بيكون عبارة عن JSON وبيتكون من اتنين Property واحد للـ Algorithm والتاني للـ Token Type
  • الـ Payload: الـ Data او الـ Claims وبتكون نوعين:
    • ياما Registered claim يعني معروفة predefined وثابتة لكل الـ Users زي الـ Subject وفيه الـ audience اللي هو بتعمله لمين وفيه الـ issuer اللي هو المصدر (اللي عمل التوكين)
    • وتاني حاجة عندنا اللي هي الـ Private Claims اللي بتختلف من User للتاني
    • ممكن ابعت الـ Password فلما أبعته للـ Front-end يعرف يفك ويعرف الـ Password ودي اللي بنقول عليها Information Exchange
  • الـ Signature: فنبدأ نشوف الـ Security Algorithm اللي احنا اخترناه وكأنه بياخد Parameters

Auth Service

اللي هيكون جواها Function بتعمل Refresh Token وهيبقا فيها حاجات كتير بس النهاردة هيبقا بس اللي بتعمل Generate Token

ميزة الـ Refresh Token: قولنا ان الـ Front-end بيخزن الـ Token في الـ Local storage والمفروض انه يحصله Expire في خلال يوم مثلًا، فممكن ياخد الـ Token بتاع واحد وافتحه عندي بنفس الـ Token ودا اللي كان بيحصل مع Watch it فميزته انه بيعمل Expire بعد نص دقيقة وبيتغير كل شوية وبيتعمله Refresh

Interface

نروح في بروجكت الـ Core ونعمل Services.Contract جديد

public interface IAuthService
{
	Task<string> CreateTokenAsync(AppUser user, UserManager<AppUser> userManager);
}

Class

نروح في Project الـ Service

public class AuthService : IAuthService
{
	private readonly IConfiguration _configuration;
	public AuthService(IConfiguration configuration)
	{
		_configuration = configuration;
	}
	public Task<string> CreateTokenAsync(AppUser user, UserManager<AppUser> userManager)
	{
		// Private Claims
		var authClaims = new List<Claim>()
		{
			new Claim(ClaimTypes.GivenName, user.UserName),
			new Claim(ClaimTypes.Email, user.Email)
		};
 
		var userRoles = await userManager.GetRolesAsync(user);
		foreach (var role in userRoles)
		{
			authClaims.Add(new Claim(ClaimTypes.Role, role));
		}
 
		var authKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:SecretKey"]));
 
		var token = new JwtSecurityToken(
			audience: _configuration["JWT:ValidAudience"],
			issuer: _configuration["JWT:ValidIssuer"],
			expires: DateTime.UtcNow.AddDays(double.Parse(_configuration["JWT:DurationInDays"])),
			claims: authClaims,
			signingCredentials: new SigningCredentialsI(authKey, SecurityAlgorithms.HmacSha256Signature)
		);
		// pass to ctor By name
 
		return new JwtSecurityTokenHandler().WriteToken(token);
		// Object Member
	}
}
 
// appsettings
"JWT": {
	"SecretKey": "StrONGKAutHENTICATIONKEy",
	"ValidAudience": "SecuiredApiUsers",
	"ValidIssuer": "ALX",
	"DurationInDays": 1
}, // don't forget ,

محتاج نعمل Install للـ Package بتاع الـ JWT وهنعمل كدا في الـ Project Services اسم الـ Package هو Microsoft.AspNetCore.Authentication.JwtBearer

هنبدأ بقا دلوقتي نعرف الـ 3 حاجات اللي قولنا عليهم فوق وأول حاجة هي الـ Claims وخصوصا الـ Private Claims:

  • هنعمل var اسمه authClaims ويبقا عبارة عن List من النوع اللي اسمه Claim
  • نبدأ نعمله Initialize وهو بياخد حاجتين الـ type والـ value

ممكن كمان اضيفله الـ Role بتاع الـ User فهضطر اني اخليه ياخد UserManager فالفرونت لو عايز يعرف يفك الـ Role ويعرف

محتاجين كمان نضيف الـ Secret Key بس احنا مش هنكتب أي داتا هنا فأنا لو محتاج أعملها Configure او حاجة فبعملها في فايل appsettings فهو بيشيل معلومات ممكن اغيرها في وقت من الأوقات JwtSecret.com - Generate JWT Secrets Online

دلوقتي المفروض احدد Registered Claims والـ Security Algorithm بس الحاجات دي هحددها وانا ببني الـ Token Object ودا اللي هستخدمه عشان أبني الـ Token

دي الـ Claims اللي بستخدمها عشان اعمل Generate Token ودي برضو اللي هستخدمها عشان أشوف الـ Token صح ولا لا

ممكن استخدم الـ Subject

ممكن نستخدم كمان الـ Expire

هنحتاج نبعت كمان الـ Authentication Claims الـ Private

محتاجين نبعت الـ Secret Key والـ Security Algorithm

دي عبارة عن Common class مبيتعملش غير مرة واحدة للشركة فخد بالك انت ممكن متعملوش اصلا كتير وممكن تسأل السينيورز على حاجات فيه عادي