আজকের লেকচারে স্বাগতম!

কোথায় আছি আমরা? আপনি বর্তমানে Section 25: Identity-তে আছেন। গত লেকচারে আমরা Login এবং Logout ফাংশনালিটি শেষ করেছি। কিন্তু একটি বড় সমস্যা হলো, যে কেউ চাইলে লগইন না করেই সরাসরি URL (যেমন: /persons/index) টাইপ করে আমাদের ওয়েবসাইটের ভেতরের পেজগুলোতে ঢুকে যেতে পারছে! আজকে আমরা শিখবো Authorization Policy কনফিগার করার মাধ্যমে কীভাবে পুরো অ্যাপ্লিকেশনটিকে সিকিউর করতে হয় এবং লগইন ছাড়া ইউজারদের অটোমেটিকভাবে লগইন পেজে রিডাইরেক্ট করতে হয়। চলুন শুরু করি!


📝 Quick Summary for Revision

ভবিষ্যতে দ্রুত রিভিশন দেওয়ার জন্য পুরো লেকচারের মূল বিষয়গুলো নিচে লিস্ট করা হলো:

  • Authentication vs Authorization: Authentication মানে হলো ইউজারের পরিচয় নিশ্চিত করা (লগইন করা আছে কিনা)। আর Authorization মানে হলো ওই ইউজারের নির্দিষ্ট পেজে যাওয়ার পারমিশন আছে কিনা।
  • Middleware Order: Program.cs ফাইলে UseRouting এর পর প্রথমে UseAuthentication, তারপর UseAuthorization এবং শেষে MapControllers কল করতে হয়।
  • Fallback Policy: AddAuthorization সার্ভিসে FallbackPolicy সেট করে পুরো অ্যাপ্লিকেশনকে বাই-ডিফল্ট সিকিউর করা হয়, যেন লগইন ছাড়া কোনো পেজ অ্যাক্সেস করা না যায়।
  • LoginPath Setup: ConfigureApplicationCookie ব্যবহার করে বলে দেওয়া হয় যে, আনঅথোরাইজড ইউজারকে কোন URL-এ রিডাইরেক্ট করতে হবে (যেমন: /Account/Login)।
  • [AllowAnonymous]: পুরো অ্যাপ্লিকেশন সিকিউর করার পর, লগইন বা রেজিস্টার পেজ যেন সবাই দেখতে পারে, সেজন্য AccountController-এর ওপর এই অ্যাট্রিবিউটটি ব্যবহার করা হয়।

🧠 Comprehensive Breakdown

এখানে লেকচারের প্রতিটি বিষয় বিস্তারিতভাবে এবং ধাপে ধাপে ব্যাখ্যা করা হলো:

১. Middleware Order in Pipeline (Priority: 10/10)

সবার প্রথমে আমাদের Request Pipeline-এ Authorization এনাবল করতে হবে। Program.cs ফাইলে Middleware-এর সিরিয়াল খুবই সেনসিটিভ।

Why this order? প্রথমে UseRouting ঠিক করে যে রিকোয়েস্টটি কোন কন্ট্রোলারে যাবে। এরপর UseAuthentication Identity Cookie চেক করে ইউজারের পরিচয় বের করে। এরপর UseAuthorization চেক করে যে ওই ইউজারের পারমিশন আছে কিনা। পারমিশন থাকলে MapControllers তাকে কাঙ্ক্ষিত পেজটি দেখায়।

💻 Code Implementation (Program.cs):

app.UseRouting();
 
// 1. Check WHO the user is
app.UseAuthentication(); 
 
// 2. Check WHAT they are allowed to do
app.UseAuthorization();  
 
app.MapControllers();
 

২. Setting up Global Authorization Policy (Priority: 10/10)

আমরা চাই আমাদের অ্যাপ্লিকেশনের সব কন্ট্রোলার এবং অ্যাকশন মেথড বাই-ডিফল্ট সিকিউর থাকুক। অর্থাৎ, ইউজার লগইন করা না থাকলে সে কিছুই দেখতে পারবে না। এর জন্য আমরা IoC Container-এ একটি গ্লোবাল Fallback Policy সেট করবো।

Why Fallback Policy? প্রতিটি কন্ট্রোলারের ওপর ম্যানুয়ালি [Authorize] অ্যাট্রিবিউট লেখার চেয়ে গ্লোবালি রুলস সেট করে দেওয়া অনেক বেশি নিরাপদ। এতে করে ভুলে কোনো পেজ সিকিউর করতে মনে না থাকলেও, বাই-ডিফল্ট সেটি সিকিউর থাকবে।

💻 Code Implementation (StartupExtensions.cs বা Program.cs):

using Microsoft.AspNetCore.Authorization;
 
// AddDbContext এবং AddIdentity এর পর এটি লিখতে হবে
services.AddAuthorization(options =>
{
    // গ্লোবাল রুলস তৈরি করা হচ্ছে
    options.FallbackPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser() // ইউজারকে অবশ্যই লগইন থাকতে হবে
        .Build();
});
 

৩. Configuring the Login Path (Priority: 9/10)

উপরের পলিসি সেট করার পর, যদি কোনো লগআউট করা ইউজার /Persons/Index-এ যাওয়ার চেষ্টা করে, তবে ফ্রেমওয়ার্ক তাকে রিজেক্ট করবে। কিন্তু রিজেক্ট করে কোথায় পাঠাবে? আমাদের বলে দিতে হবে যে, “লগইন না থাকলে তাকে /Account/Login পেজে পাঠিয়ে দাও।”

💻 Code Implementation (StartupExtensions.cs):

services.ConfigureApplicationCookie(options =>
{
    // লেকচারার শুরুতে "~" ব্যবহার করে একটি এরর পেয়েছিলেন। 
    // এটি সবসময় "/" দিয়ে শুরু হতে হবে।
    options.LoginPath = "/Account/Login"; 
});
 

৪. Exposing Login/Register via [AllowAnonymous] (Priority: 10/10)

এখন একটি বড় সমস্যা তৈরি হয়েছে! আমরা গ্লোবালি সব পেজ লক করে দিয়েছি। এখন লগআউট করা ইউজার /Account/Login পেজে গেলেও সিস্টেম তাকে ঢুকতে দিবে না! কারণ গ্লোবাল পলিসি বলছে “আগে লগইন করে আসো!”। এই ডেডলক ভাঙ্গার জন্য আমাদের AllowAnonymous অ্যাট্রিবিউট ব্যবহার করতে হবে।

Why AllowAnonymous? এটি গ্লোবাল Authorization পলিসিকে ওভাররাইড (override) করে এবং স্পেসিফিক পেজগুলোকে লগইন ছাড়াই ভিজিট করার অনুমতি দেয়।

💻 Code Implementation:

  • AccountController.cs:
using Microsoft.AspNetCore.Authorization;
 
[AllowAnonymous] // এই কন্ট্রোলারের সব অ্যাকশন লগইন ছাড়াই ভিজিট করা যাবে
public class AccountController : Controller
{
    // Login, Register, Logout methods...
}
 
  • HomeController.cs (Error Page): যদি সিস্টেমে কোনো ক্র্যাশ বা এরর হয়, ইউজার লগইন না থাকলেও যেন এরর পেজ দেখতে পারে, তাই সেখানেও এটি বসাতে হবে।
[AllowAnonymous]
[Route("[action]")]
public IActionResult Error()
{
    return View();
}
 

৫. ReturnUrl - A Teaser for Next Lecture (Priority: 8/10)

সব কনফিগারেশন শেষে যখন আমরা লগআউট অবস্থায় /Persons/Index লিখে এন্টার দিবো, তখন সিস্টেম অটোমেটিক রিডাইরেক্ট করে URL-টি এমন করে দিবে: http://localhost:5000/Account/Login?ReturnUrl=%2FPersons%2FIndex

এখানে ReturnUrl কোয়েরি প্যারামিটারটির কাজ হলো ইউজার অরিজিনালি কোন পেজে যেতে চেয়েছিলো তা মনে রাখা। যাতে করে ইউজার লগইন ফর্ম ফিলাপ করার সাথে সাথে সিস্টেম তাকে আবার সেই কাঙ্ক্ষিত পেজে (Persons) নিয়ে যেতে পারে। এটি নিয়ে আমরা পরবর্তী লেকচারে বিস্তারিত কাজ করবো।


🌟 Best Practices & Modern Updates (.NET 10 Context)

  • Default Secure Mindset: সিকিউরিটির দুনিয়ায় একটি রুলস হলো “Secure by Default, Allow by Exception”। লেকচারার যে FallbackPolicy পদ্ধতিটি দেখিয়েছেন এটি ঠিক সেই রুলসটিই ফলো করে (সব লক করে স্পেসিফিক পেজগুলো AllowAnonymous করা)। এটি অত্যন্ত প্রফেশনাল এবং স্ট্যান্ডার্ড প্র্যাকটিস।
  • Minimal API Context (.NET 8/10): আপনি যদি MVC এর বদলে Minimal APIs ব্যবহার করেন, তবে গ্লোবালি পলিসি সেট করার পাশাপাশি রুট লেভেলে app.MapControllers().RequireAuthorization(); ব্যবহার করেও সহজেই সব এন্ডপয়েন্ট সিকিউর করে ফেলা যায়।
  • Separate Layout for Auth Pages: লেকচারার শেষে একটি চমৎকার আইডিয়া দিয়েছেন। যেহেতু লগইন বা রেজিস্টার পেজে মেনুবারের কোনো কাজ নেই, তাই এই দুটি পেজের জন্য _Layout.cshtml-এর ওপর নির্ভর না করে একটি সম্পূর্ণ আলাদা লেআউট (যেমন: _AuthLayout.cshtml) তৈরি করা উচিত, যেখানে শুধু একটি ক্লিন ব্যাকগ্রাউন্ড এবং সেন্টারে ফর্মটি থাকবে।

অসাধারণ! আমাদের অ্যাপ্লিকেশন এখন পুরোপুরি সিকিউর। পরবর্তী লেকচারে আমরা ReturnUrl নিয়ে কাজ করবো, যাতে ইউজার এক্সপেরিয়েন্স (UX) আরও স্মুথ হয়!