সরাসরি পর্বে যান
পর্ব ১৭ · ৮০-এর মধ্যে · মডিউল ৩

Session আর token — cookie, JWT আর নিরাপদ logout

Sessions and Tokens — Cookies, JWT, Refresh Rotation & Real Logout

Taught in Bangla, this lesson explains why HTTP needs sessions, what makes a session ID safe with a guessing-time calculation, session fixation prevention, what each cookie flag stops, timeouts and real server-side logout, JWT structure and correct verification steps, refresh token rotation with reuse detection, where to keep tokens in a browser, opaque tokens versus JWT, and theft signals with step-up.

এই পর্বে যা শিখবেন

  • HTTP-র session কেন লাগে, আর server-side session কীভাবে চলে
  • নিরাপদ session ID-র শর্ত, অনুমানের সময়ের হিসাব আর session fixation ঠেকানো
  • প্রতিটি cookie flag ঠিক কী থামায়, আর কী থামায় না
  • JWT-র গঠন, HS256, RS256 আর EdDSA, এবং যাচাইয়ের সঠিক ধাপ
  • Refresh token rotation, reuse detection, device list আর সত্যিকারের logout
  • Browser-এ token রাখার জায়গা, চুরির সংকেত, step-up আর opaque বনাম JWT সিদ্ধান্ত

সীমারেখা: এই পর্ব রক্ষকের জন্য। এখানে নিজের system-এর session নকশা আর যাচাইয়ের নিয়ম আছে। সব কোড নকল key আর খেলনা ডেটায় চলে। অন্যের cookie বা token নেওয়া, ব্যবহার করা বা পরীক্ষা করা অনুমতি ছাড়া অপরাধ হতে পারে। পর্ব ৬-এর লিখিত অনুমতির নিয়ম এখানেও প্রযোজ্য।

১ · HTTP মনে রাখে না, তাই session লাগে

HTTP নিজে থেকে আগের কথা মনে রাখে না। প্রতিটি request নতুন, যেন আগের সঙ্গে কোনো সম্পর্ক নেই। একে বলে stateless. Password যাচাই হলো একবার, কিন্তু পরের ক্লিকে server আর জানে না আপনি কে। প্রতি ক্লিকে password পাঠানো বিপজ্জনক, ঝামেলারও। তাই login-এর পর server একটি ছোট প্রমাণ দেয়। পরের প্রতিটি request সেই প্রমাণ সঙ্গে নিয়ে আসে। এই ধারাবাহিক পরিচয়ের নামই session.

একটি অফিসের গেটের কথা ভাবুন। প্রথম দিন দারোয়ান পরিচয়পত্র দেখে একটি নম্বর দেওয়া টোকেন দিলেন, আর রেজিস্টার খাতায় লিখলেন “টোকেন ৪২, রহিমা, হিসাব বিভাগ”। এরপর শুধু টোকেন দেখালেই চলে। এটি server-side session: টোকেনে কোনো তথ্য নেই, তথ্য আছে খাতায়।

আরেক অফিসে দারোয়ান খাতা রাখেন না। সেখানে কর্তৃপক্ষের সিলমোহর করা গেট পাস দেওয়া হয়, তাতে নাম, বিভাগ আর মেয়াদ লেখা। দারোয়ান শুধু সিল পরীক্ষা করেন। এটি JWT-এর মতো। সুবিধা, খাতা লাগে না। অসুবিধা, পাস একবার দিলে ফেরত আনা কঠিন।

তথ্য কোথায় থাকে: খাতায়, না পাসে

Server-side session vs signed token, with the trust boundary

Server-side session আর JWT-এর তুলনা অবিশ্বস্ত Server: trust boundary-র ভেতরে Server-side session Browser শুধু এলোমেলো ID কোনো তথ্য নেই App server Store user, role সময়ের হিসাব Row মুছলেই session সঙ্গে সঙ্গে শেষ। দাম: প্রতি request-এ store দেখতে হয়। স্বাক্ষর করা token (JWT) Browser তথ্য আর স্বাক্ষর পড়া যায় API শুধু key দিয়ে যাচাই কোনো store দেখে না Token মেয়াদ পর্যন্ত চলতেই থাকে। লাভ: store ছাড়াই অনেক service যাচাই করে।
ছবি ১৭.১ — Browser trust boundary-র বাইরে। সেখান থেকে যা আসে, সবই যাচাই করতে হয়।
মূল ধারণা

Cookie বা JWT, দুটোই সাধারণত bearer token, মানে “যাঁর হাতে আছে, তিনিই মালিক”। Login-এর MFA দরজার তালা, আর session হলো দরজা খোলার পরের চাবি। এই চাবি নিজে দ্বিতীয় কোনো প্রমাণ চায় না। তাই পর্ব ১৩-এর মতো মজবুত password, পর্ব ১৫-এর login নীতি আর পর্ব ১৬-এর MFA থাকলেও session দুর্বল হলে পুরো ব্যবস্থা দুর্বল।

System design-এর দিক থেকে session store কীভাবে মাপবেন, কীভাবে ভাগ করবেন, তা আছে System Design কোর্সের session পর্বে. এখানে আমরা দেখব নিরাপত্তার দিক।

২ · Session ID: এলোমেলো, লম্বা আর login-এর পরে নতুন

Server-side session-এ browser পায় শুধু একটি session ID. এর কাজ একটাই, store-এর একটি সারি খুঁজে দেওয়া। তাই এতে কোনো অর্থ থাকবে না: ব্যবহারকারীর নম্বর, সময় বা email নয়। তিনটি শর্ত মনে রাখুন।

  • এলোমেলো: ID আসবে CSPRNG থেকে, যেমন Python-এর secrets. সাধারণ random বা ক্রমিক সংখ্যা চলবে না।
  • যথেষ্ট লম্বা: OWASP Session Management Cheat Sheet ন্যূনতম ৬৪ bit entropy চায়, মানে পুরো এলোমেলো হলে ১৬টি hex অক্ষর। NIST SP 800-63B (Revision 4, ২০২৫)-ও session secret-এর জন্য অন্তত ৬৪ bit চায়। ১২৮ bit বা ২৫৬ bit নিতে খরচ প্রায় নেই, তাই বেশিই নিন।
  • পুরোটাই এলোমেলো: লম্বা ID-র অর্ধেক স্থির হলে শক্তিও অর্ধেক নয়, তার চেয়েও খারাপ। ১৬ hex অক্ষরের ৮টি স্থির হলে থাকে ৩২ bit.

অনুমান করতে কত সময় লাগবে?

হিসাবটি সহজ। ধরুন ID-তে b bit entropy, আক্রমণকারী প্রতি সেকেন্ডে rটি অনুমান পাঠাতে পারে, আর একই সময়ে Sটি session বৈধ। প্রতি অনুমানে সফল হওয়ার সম্ভাবনা S / 2^b. তাই যেকোনো একটি session মেলাতে গড় অনুমান 2^b / S, আর গড় সময়:

E = 2^b / (r × S) সেকেন্ড

লক্ষ করুন, S যত বড়, লক্ষ্য তত সহজ, কারণ যেকোনো একজনের session মিললেই ক্ষতি। নিচের হিসাবে r = 10,000 আর S = 100,000 ধরা হয়েছে। দুটোই ধরে নেওয়া মান।

// গড় অনুমান-সময়: E = 2^b / (r × S)
const r = 1e4;     // প্রতি সেকেন্ডে অনুমান (ধরে নেওয়া মান)
const S = 1e5;     // একসঙ্গে বৈধ session (ধরে নেওয়া মান)
const YEAR = 365.25 * 24 * 3600;

function pretty(sec) {
  if (sec < 3600) return sec.toFixed(1) + " seconds";
  return (sec / YEAR).toExponential(2) + " years";
}

console.log("bits  hex-chars  base64url-chars  expected time");
for (const b of [32, 64, 128]) {
  const hex = String(b / 4).padEnd(10);
  const b64 = String(Math.ceil(b / 6)).padEnd(16);
  const sec = 2 ** b / (r * S);
  console.log(String(b).padEnd(5), hex, b64, pretty(sec));
}

// rate limit করলে r কমে: 64 bit, 10 অনুমান/সেকেন্ড
console.log("64 bit, r=10/s:", pretty(2 ** 64 / (10 * S)));

আউটপুট: ৩২ bit-এ 4.3 seconds, ৬৪ bit-এ 5.85e+2 years, মানে প্রায় ৫৮৫ বছর, আর ১২৮ bit-এ 1.08e+22 years. শেষ লাইনে 64 bit, r=10/s: 5.85e+5 years: হার ১০০০ ভাগের এক হলে সময় ১০০০ গুণ। অর্থাৎ ছোট ID-র ক্ষতি rate limit দিয়ে পুরো ঢাকা যায় না, তবে সে বাড়তি একটি স্তর। ১২৮ bit-এ hex-এ লাগে ৩২ অক্ষর, base64url-এ ২২ অক্ষর। OWASP-এর cheat sheet-এ ৬৪ bit-এর জন্য প্রায় ৫৮৫ বছরের কথা আছে। আমাদের ধরে নেওয়া S দিয়ে একই ফল আসে।

import hashlib, secrets

sid = secrets.token_urlsafe(32)                 # 256 bit, cookie-তে যাবে
sid_hash = hashlib.sha256(sid.encode()).hexdigest()   # store-এ শুধু এটি

এই উদাহরণের দ্বিতীয় লাইনটি একটি ভালো অভ্যাস। Store-এ ID-র বদলে তার SHA-256 রাখলে store ফাঁস হলেও সেখান থেকে চালু cookie পাওয়া যায় না। ID নিজেই ২৫৬ bit এলোমেলো, তাই এখানে পর্ব ১৩-এর ধীর hash লাগে না। পর্ব ৯-এর দ্রুত hash-ই যথেষ্ট। Log-এ কাঁচা ID কখনো নয়। OWASP salt দেওয়া hash লিখতে বলে, যাতে ঘটনা মেলানো যায়, কিন্তু ID হাতে না আসে।

Session fixation: ধারণা আর প্রতিরক্ষা

Session fixation-এ সমস্যাটি চুরি নয়, উল্টো। কোনো কারণে ব্যবহারকারীর browser-এ আগে থেকেই এমন একটি ID বসে আছে, যা অন্য কেউ জানেন। Login-এর পর server যদি সেই ID-টিই রেখে দেয় আর তাকে “লগইন করা” বলে ধরে, তাহলে জানা ID-টি সরাসরি লগইন করা session হয়ে যায়। ভুলটি ID নিয়ে নয়, ভুল হলো পরিচয় বদলানোর সময় ID না বদলানো।

প্রতিরক্ষা সোজা:

  • Login, password বদল, role বদল, অর্থাৎ যেকোনো privilege বদলে নতুন ID, পুরোনোটি server-এ মুছে ফেলা।
  • শুধু server-এর তৈরি ID গ্রহণ করা। অচেনা ID এলে নতুন ID দেওয়া এবং ঘটনাটি log করা।
  • ID শুধু cookie-তে। URL-এ কখনো নয়, কারণ URL ইতিহাস, log আর Referer-এ ছড়ায়।
  • __Host- নাম ব্যবহার করা, যাতে অন্য subdomain সেই নামের cookie বসাতে না পারে।

নিচের ধাপগুলোতে একটি login থেকে logout পর্যন্ত পুরো পথ দেখুন। Cookie-র মানটি নকল। Store-এর hash হলো example-token-3fa9-এর আসল SHA-256-এর শুরুর অংশ।

  1. Browsercookie jarঅবিশ্বস্ত দিক
  2. App serverlogin, verifyনিয়ম এখানে
  3. Session storesid_hashআসল অবস্থা
GET /loginলগইনের আগে
Set-Cookie: anon=example-anon-7c21;
  Path=/; Secure; HttpOnly
লগইন-পূর্ব ID, পরিচয় এখনো নেই
POST /loginTLS-এর ভেতরে
user=rahima, password=<user-input>
hash মিলল, MFA ঠিক আছে
privilege বদলাচ্ছে: ID-ও বদলাতে হবে
session storeনতুন সারি
anon row: deleted
sid_hash   = 0c4cb2f16f59af1f…
user       = rahima
created    = 10:00
last_seen  = 10:00
device     = Chrome, Android
200 OKBrowser-এ ফেরা
Set-Cookie: __Host-sid=
  example-token-3fa9;
  Path=/; Secure; HttpOnly;
  SameSite=Lax
Set-Cookie: anon=; Path=/;
  Max-Age=0
GET /ordersপরের request
Cookie: __Host-sid=
  example-token-3fa9
sha256(ID) = 0c4cb2f16f59af1f…
সারি পাওয়া গেছে
10:07: দুই সীমার ভেতরে
last_seen  = 10:07
200 OK, rahima-র অর্ডার
POST /logoutশেষ করা
store: 0c4cb2f16f59af1f… deleted
Set-Cookie: __Host-sid=; Path=/;
  Secure; HttpOnly; Max-Age=0
পুরোনো কপি এলে: সারি নেই, 401
  1. লগইনের আগে। অনেক সাইটে ঝুড়ি বা ভাষার জন্য একটি লগইন-পূর্ব ID থাকে। এই ID-তে কোনো পরিচয় নেই, আর একে বিশ্বাস করার কারণও নেই।
  2. পরিচয় যাচাই। Password TLS-এর ভেতরে এল, hash মিলল, MFA-ও ঠিক। ব্যবহারকারী এখন বেনামি থেকে rahima, অর্থাৎ privilege বদলাচ্ছে। Session fixation ঠেকানোর মুহূর্ত এটিই।
  3. নতুন ID, পুরোনোটি শেষ। লগইন-পূর্ব সারি মুছে গেল। নতুন এলোমেলো ID তৈরি হলো। Store-এ রইল তার hash 0c4cb2f1…, সঙ্গে user, দুই সময় আর device-এর বিবরণ।
  4. Cookie পাঠানো। __Host-sid নামের cookie গেল Secure, HttpOnly, SameSite=Lax আর Path=/ সহ। পুরোনো anon cookie Max-Age=0 দিয়ে মুছে দেওয়া হলো।
  5. পরের request. Browser নিজেই cookie পাঠাল। Server ID-র hash বানিয়ে সারি পেল, সীমা দেখল, আর last_seen 10:00 থেকে 10:07 করল।
  6. Logout. আসল কাজ server-এ: সারিটি মুছে গেল। Cookie মোছা দ্বিতীয় ধাপ। কেউ পুরোনো cookie-র কপি পাঠালে সারি পাওয়া যায় না, তাই উত্তর 401.

৩ · Cookie-র flag: কোনটি কী থামায়

একটি cookie হলো ছোট নাম আর মান, যা server বলে দেয়, আর browser পরের request-এ নিজে থেকে পাঠায়। কয়েকটি attribute ঠিক করে কখন, কোথায়, কার কাছে সেটি যাবে। ভালো একটি শুরুর লাইন এমন:

Set-Cookie: __Host-sid=example-token; Path=/; Secure; HttpOnly; SameSite=Lax
Attributeযা করেযা করে না
SecureCookie শুধু HTTPS-এ যায়Device-এর ভেতরে সুরক্ষা দেয় না; HSTS-এর বিকল্পও নয়
HttpOnlyJavaScript document.cookie দিয়ে পড়তে পারে নাRequest পাঠানো থামায় না; injected script তখনো আপনার হয়ে request করতে পারে
SameSiteStrict: শুধু same-site. Lax: বাইরের সাইট থেকে লিংকে আসার মতো নিরাপদ navigation-এও যায়। None: সবখানে, Secure আবশ্যকCSRF-এর পূর্ণ সমাধান নয়, একটি স্তর মাত্র (পর্ব ৪১)
Domainদিলে সেই domain আর সব subdomain-এ যায়। না দিলে শুধু যে host বসিয়েছে সেখানেনা দেওয়াই ভালো; দিলে একটি দুর্বল subdomain-ও cookie পায়
Pathকোন path-এ cookie যাবে তা ঠিক করেনিরাপত্তার সীমা নয়; MDN স্পষ্ট বলে একই origin-এর অন্য path থেকে পড়া ঠেকায় না
Max-Age, ExpiresBrowser কতক্ষণ রাখবে। না দিলে session cookie, browser বন্ধে যায়Timeout নয়; browser-এর session restore cookie ফিরিয়ে আনতে পারে
__Host- নামBrowser তখনই নেয় যখন Secure আছে, HTTPS থেকে এসেছে, Domain নেই, Path=/পুরোনো browser-এ এই যাচাই নাও থাকতে পারে

NIST SP 800-63B-4 session cookie-র জন্য HTTPS-only বাধ্যতামূলক করেছে, আর HttpOnly ও SameSite=Lax বা Strict সুপারিশ করেছে। একই দলিল বলে, cookie-র মেয়াদের ওপর ভরসা করে timeout চালানো যাবে না। OWASP Strict-কে আগে রাখে, তবে বাইরের লিংক থেকে এলে লগইন না দেখানোর মতো অসুবিধা আসতে পারে। তাই ব্যাংকিং ধরনের সাইটে Strict, সাধারণ সাইটে Lax বহুল প্রচলিত আপস।

HttpOnly-র সীমা বুঝুন। এটি cookie পড়া আটকায়, XSS আটকায় না। পাতায় বাইরের script চললে সেটি browser-এর ভেতর থেকেই আপনার পরিচয়ে request পাঠাতে পারে, আর cookie নিজে থেকে সঙ্গে যায়। তাই আসল প্রতিরক্ষা output encoding আর CSP, পর্ব ৪০-এ দেখবেন।

৪ · Timeout আর সত্যিকারের logout

Session অনন্তকাল চলতে পারে না। সময়ের সীমা না থাকলে একবার ফাঁস হওয়া cookie চিরকাল কাজ করে। দুটি ঘড়ি লাগে, দুটি আলাদা বিপদের জন্য।

Idle timeout

Idle timeout শেষ কাজের পর থেকে গোনে। সাইবার ক্যাফেতে বা অফিসে কম্পিউটার খোলা রেখে উঠে গেলে এটি বাঁচায়। প্রতিটি request-এ ঘড়ি আবার শূন্য হয়।

OWASP: উচ্চমূল্যের অ্যাপে ২–৫ মিনিট, কম ঝুঁকিতে ১৫–৩০ মিনিট

Absolute timeout

Absolute timeout login থেকে গোনে, কাজ চললেও থামে না। চুরি হওয়া cookie নিয়মিত ব্যবহার করে কেউ idle ঘড়ি এড়াতে পারলেও এখানে সীমা আসে।

OWASP-এর উদাহরণ: সারাদিনের অফিস অ্যাপে ৪–৮ ঘণ্টা

NIST SP 800-63B-4 অনুযায়ী AAL2-তে সামগ্রিক পুনঃপ্রমাণীকরণ ২৪ ঘণ্টার মধ্যে আর inactivity ১ ঘণ্টা (দুটিই সুপারিশ), AAL3-তে ১২ ঘণ্টা (বাধ্যতামূলক) আর ১৫ মিনিট (সুপারিশ)। মনে রাখবেন, এই সংখ্যা একটি মানদণ্ডের, সবার জন্য একই মান নয়। অ্যাপের ঝুঁকি দেখে ঠিক করুন, আর সবচেয়ে জরুরি কথা: দুটি ঘড়িই চলবে server-এ। Browser-এর timer যে কেউ বদলাতে পারে।

নিচের খেলনা store-এ IDLE = 15 আর ABSOLUTE = 120 মিনিট। ঘড়ি সিমুলেটেড। তিনজনের গল্প আলাদা, চালিয়ে দেখুন।

// খেলনা session store: ID real নয়, ঘড়ি সিমুলেটেড (মিনিট)
function mulberry32(a) { return () => { a = a + 0x6D2B79F5 | 0;
  let t = Math.imul(a ^ a >>> 15, 1 | a);
  t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
  return ((t ^ t >>> 14) >>> 0) / 4294967296; }; }
const rnd = mulberry32(17);
const IDLE = 15, ABSOLUTE = 120;
const store = new Map();

function login(user, now) {
  const id = "sid-" + Math.floor(rnd() * 2 ** 24).toString(16).padStart(6, "0");
  store.set(id, { user, created: now, last: now });
  return id;
}
function request(id, now) {
  const s = store.get(id);
  if (!s) return "401 no session";
  if (now - s.last >= IDLE) { store.delete(id); return "401 idle timeout"; }
  if (now - s.created >= ABSOLUTE) { store.delete(id); return "401 absolute timeout"; }
  s.last = now;
  return "200 " + s.user;
}
const log = (t, msg) => console.log("t=" + String(t).padEnd(4), msg);

const a = login("rahima", 0);
for (const t of [10, 20, 40, 41]) log(t, a + " " + request(a, t));

const b = login("karim", 50);
for (let t = 64; t <= 176; t += 14) log(t, b + " " + request(b, t));

const c = login("sadia", 200);
log(205, c + " " + request(c, 205));
store.delete(c);                        // logout: server-এ মুছল
log(207, c + " " + request(c, 207) + " (same cookie)");
console.log("rows left in store:", store.size);

Rahima ২০ মিনিট চুপ ছিলেন, তাই t=40 … 401 idle timeout, আর সারি মুছে যাওয়ায় পরের লাইনে 401 no session. Karim প্রতি ১৪ মিনিটে কাজ করছেন, তাই idle ঘড়ি কখনো ১৫ ছোঁয় না। তবু ১২৬ মিনিটে t=176 … 401 absolute timeout. Idle একা থাকলে এই session কখনো শেষ হতো না। Sadia logout করলেন, আর t=207 … 401 no session (same cookie): একই cookie, কিন্তু server-এ সারি নেই। শেষে rows left in store: 0.

Logout মানে কী?

অনেক সাইটের logout শুধু browser-এর cookie মুছে দেয়। ব্যবহারকারী লগইন পাতা দেখেন, কিন্তু cookie-র কোনো কপি কোথাও থাকলে সেটি দিব্যি চলে। এটি রেস্তোরাঁর ক্যাশমেমো ছিঁড়ে ফেলার মতো, খাতায় হিসাব থেকেই যায়। সত্যিকারের logout-এ যা হয়:

  1. Server session-এর সারি মুছে ফেলে। এটিই আসল কাজ, OWASP-ও একে বাধ্যতামূলক বলে।
  2. Refresh token থাকলে তার পুরো family বাতিল করে।
  3. Cookie মুছতে একই নাম, Path আর attribute দিয়ে Max-Age=0 পাঠায়।
  4. সংবেদনশীল পাতায় Cache-Control: no-store রাখে, প্রয়োজনে Clear-Site-Data header-ও পাঠায়, যাতে পেছনে ফিরে পুরোনো পাতা না আসে।
  5. ঘটনাটি log করে: কে, কোন device, কখন।

একটি ফোন হারালে শুধু সেই device থেকে logout সম্ভব নয়। তাই ভালো সাইটে থাকে একটি device list, অর্থাৎ বর্তমান session-এর তালিকা: কোন device, কখন শেষ দেখা, মোটামুটি কোন এলাকা। প্রতিটি সারির পাশে “সাইন আউট” চাপলে store-এর সেই সারি মুছে যায়। “সব device থেকে সাইন আউট” আর password বদলে অন্য সব session শেষ করা, দুটোই রাখুন। ব্যাখ্যা সহজ: খাতার সারি মুছলেই সেই টোকেন অকেজো।

৫ · JWT: তিন টুকরো, এক স্বাক্ষর

RFC 7519 (২০১৫) JWT (JSON Web Token)-এর সংজ্ঞা দেয়। এটি কিছু claim, মানে দাবি, যেগুলো স্বাক্ষর করা অবস্থায় এক জায়গা থেকে আরেক জায়গায় যায়। স্বাক্ষরের নিয়ম আছে JWS (RFC 7515)-এ। সাধারণ JWT তিনটি base64url টুকরো, মাঝে ডট।

একটি JWT-র ভেতরে

JWS compact form: header . payload . signature

JWT-র header, payload আর signature Header {"alg":"HS256","typ":"JWT"} Payload (claims) "iss":"https://auth…" "aud":"shop-api" "sub":"user-1042" "exp":1793000300 Signature key দিয়ে ওপরের দুই অংশের ওপর key ছাড়াই পড়া যায়
ছবি ১৭.২ — Base64url কোনো গোপনীয়তা দেয় না। স্বাক্ষর শুধু বদলানো ধরে।

JWT স্বাক্ষর করা, encrypt করা নয়। পর্ব ৭-এর ভাষায়, base64url একটি encoding, কোনো key লাগে না। যাঁর হাতে token, তিনি সব claim পড়তে পারেন। তাই payload-এ NID, ফোন নম্বর, ঠিকানা বা অভ্যন্তরীণ তথ্য রাখবেন না। গোপনীয়তা সত্যিই লাগলে JWE (RFC 7516) আছে, তবে OWASP প্রথমে পরামর্শ দেয় তথ্য server-এ রাখতে।

তিন ধরনের স্বাক্ষর

algধরনকে স্বাক্ষর, কে যাচাইকখন মানায়
HS256HMAC-SHA-256, symmetric (পর্ব ৯)একই গোপন key দুই কাজেইএকই সিস্টেম নিজের token নিজে যাচাই করে
RS256RSA PKCS#1 v1.5, SHA-256 (পর্ব ১০)Private key স্বাক্ষর, public key যাচাইঅনেক service বা বাইরের পক্ষ যাচাই করবে; signature বড়
EdDSAসাধারণত Ed25519 (RFC 8037)Private key স্বাক্ষর, public key যাচাইনতুন নকশায় ছোট key আর ছোট signature চাইলে

HS256-এ যিনি যাচাই করতে পারেন, তিনি স্বাক্ষরও করতে পারেন, কারণ key একই। তাই দশটি service-কে key দিলে যেকোনো একটি ফাঁসেই সব token জাল করা সম্ভব। Public-key স্বাক্ষরে যাচাইকারী জাল করতে পারে না। এই একটি কারণেই বহু service-এর জগতে asymmetric স্বাক্ষর পছন্দের। HS256-এর key CSPRNG থেকে নিন, OWASP অন্তত ২৫৬ bit চায়, আর RFC 8725 মানুষের মনে রাখার মতো password-কে key হিসেবে নিষেধ করে। RFC 9864 (২০২৫) সাধারণ EdDSA নামটি deprecated করে নির্দিষ্ট Ed25519 নাম এনেছে। তাই নতুন কাজে আপনার library কোনটি সমর্থন করে দেখে নিন।

৬ · JWT যাচাই: verifier যা করতেই হবে

Token-এর সবকিছু আসে trust boundary-র বাইরে থেকে। এর header-ও আপনার নিয়ন্ত্রণে নয়। RFC 8725 (২০২০) JWT-র সেরা অনুশীলন লিখে রেখেছে। নিয়মগুলো সংক্ষেপে:

  • Algorithm আপনি ঠিক করবেন। কোডে একটি স্থির তালিকা, যেমন শুধু HS256 বা শুধু EdDSA. Token-এর alg সেই তালিকায় না থাকলে বাতিল।
  • প্রতিটি key একটি algorithm-এর জন্য। RFC 8725-এর ভাষায়, each key MUST be used with exactly one algorithm.
  • iss মেলাতে হবে: আপনি যাঁকে বিশ্বাস করেন, token তাঁরই, আর স্বাক্ষরের key-ও তাঁর।
  • aud মেলাতে হবে: token আপনার জন্যই লেখা। একই issuer-এর অন্য অ্যাপের token এখানে চলবে না।
  • exp দেখতে হবে: এখনকার সময় তার আগে। Server-দের ঘড়ির সামান্য পার্থক্যের জন্য ছোট ছাড় চলে, ঘণ্টা নয়।
  • Header-এর key-সংক্রান্ত মান বিশ্বাস নয়। kid শুধু আপনার জানা key-এর তালিকা থেকে বাছাই করতে কাজে লাগে। jku আর x5u দেখে বাইরে থেকে key আনা চলবে না, যদি না সেই ঠিকানা আপনার allowlist-এ থাকে।

ইতিহাসের দুটি ভুল, verifier-এর দৃষ্টিতে

২০১৫ সালে প্রকাশিত নিরাপত্তা-গবেষণা দেখায়, কিছু JWT library দুটি গোড়ার ভুল করত। দুটিরই শিকড় একটি: যাচাইয়ের নিয়ম ঠিক করছিল যাচাই হওয়ার আগের token-ই।

alg = none

Standard-এ স্বাক্ষরহীন JWT-র একটি রূপ আছে। কিছু পুরোনো library header দেখে যাচাই-ই বাদ দিত। ফলে স্বাক্ষরহীন token গৃহীত হতো। নিরাপদ যাচাই: none কখনো allowlist-এ নয়।

Algorithm confusion

RS256-এর জন্য রাখা public key সবাই জানে। ভুল library header দেখে সেটিকে HMAC-এর গোপন key ভাবত। Algorithm confusion এই গোলমালের নাম। নিরাপদ যাচাই: key-এর ধরন আর algorithm একসঙ্গে বাঁধা, একই পথে MAC আর public-key মেশানো নয়।

এবার একটি আসল HS256 token একটি একটি দাবি ধরে যাচাই করি। মানগুলো নিচের Python কোডের নকল key থেকে তৈরি। NOW সিমুলেটেড।

tokenনকল key-তে তৈরি
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20iLCJhdWQiOiJzaG9wLWFwaSIsInN1YiI6InVzZXItMTA0MiIsInJvbGUiOiJjdXN0b21lciIsImV4cCI6MTc5MzAwMDMwMH0
.ebFvWKwDiqaeqpU4lmWgmMGv8iJH6N04Jhw99b5GunE
Verifier-এর টেবিল
যাচাই
প্রত্যাশিত
পাওয়া গেছে
ফল
  1. গঠন। Token ডট দিয়ে ঠিক তিন ভাগে ভাঙল। কম বা বেশি হলে এখানেই বাতিল। এখনো কোনো claim বিশ্বাস করা হয়নি।
  2. Algorithm. Header decode করে পাওয়া গেল HS256. Server-এর allowlist-এ শুধু এটিই আছে, তাই এগোনো যায়। এখানেই none বা অন্য কিছু আটকে যেত।
  3. Signature. Server নিজের key দিয়ে প্রথম দুই অংশের ওপর HMAC-SHA-256 হিসাব করল। ফল ebFvWKwDiqaeqpU4…, token-এর তৃতীয় অংশের সমান। তুলনা constant-time. এর আগে payload-এর কিছুই বিশ্বাস করা যেত না।
  4. iss. কে ইস্যু করেছে? https://auth.example.com, যা প্রত্যাশিত issuer-এর সঙ্গে হুবহু এক।
  5. aud. কার জন্য? shop-api, আর এই API নিজের নামও shop-api জানে। অন্য API-র token হলে এখানে বাতিল।
  6. exp. Token-এর মেয়াদ 1793000300, এখন 1793000000. NOW < exp, পার্থক্য 300 সেকেন্ড, তাই বৈধ।
  7. সিদ্ধান্ত। সব মিলেছে: token গৃহীত, ব্যবহারকারী user-1042. কিন্তু এটি authentication-এর শেষ, authorization-এর নয়। কী করতে পারবেন, তা আলাদা প্রশ্ন, পর্ব ১৯-এ দেখবেন।

একই নিয়ম এবার আসল hmac, hashlib আর base64 দিয়ে। শেখার জন্য এটি হাতে লেখা। বাস্তবে নিজের JWT parser না লিখে পরিচিত, রক্ষণাবেক্ষণ হওয়া library ব্যবহার করুন, আর তাতে algorithm তালিকা অবশ্যই দিন।

import base64, hashlib, hmac, json

KEY = b"example-key-lesson-only-32-bytes"     # নকল key, 32 byte
ISS, AUD = "https://auth.example.com", "shop-api"
NOW = 1793000000                              # সিমুলেটেড ঘড়ি

def b64u(b): return base64.urlsafe_b64encode(b).rstrip(b"=").decode()
def unb64u(s): return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
def js(d): return b64u(json.dumps(d, separators=(",", ":")).encode())
def mac(msg): return b64u(hmac.new(KEY, msg.encode(), hashlib.sha256).digest())

def sign(claims, alg="HS256"):
    msg = js({"alg": alg, "typ": "JWT"}) + "." + js(claims)
    return msg + "." + mac(msg)

def verify(token):
    head, body, sig = token.split(".")
    if json.loads(unb64u(head)).get("alg") != "HS256":
        return "REJECT alg"             # algorithm ঠিক করে server
    if not hmac.compare_digest(sig.encode(), mac(head + "." + body).encode()):
        return "REJECT signature"
    c = json.loads(unb64u(body))
    if c.get("iss") != ISS: return "REJECT iss"
    if c.get("aud") != AUD: return "REJECT aud"
    if not NOW < c.get("exp", 0): return "REJECT exp"
    return "ACCEPT sub=" + c["sub"]

good = {"iss": ISS, "aud": AUD, "sub": "user-1042", "role": "customer", "exp": NOW + 300}
h, b, s = sign(good).split(".")
print("payload, no key needed:", unb64u(b).decode())
print("valid     :", verify(sign(good)))
print("tampered  :", verify(h + "." + js({**good, "role": "admin"}) + "." + s))
print("expired   :", verify(sign({**good, "exp": NOW - 1})))
print("wrong alg :", verify(sign(good, alg="HS512")))
print("wrong aud :", verify(sign({**good, "aud": "other-api"})))

প্রথম লাইন payload, no key needed: {"iss":"https://auth.example.com",…} দেখায়, key ছাড়াই claim পড়া গেছে। তারপর valid : ACCEPT sub=user-1042. Role বদলানো token-এ tampered : REJECT signature, কারণ পুরোনো স্বাক্ষর নতুন payload-এর সঙ্গে মেলে না। expired : REJECT exp, wrong aud : REJECT aud. আর wrong alg : REJECT alg বিশেষভাবে দেখুন: স্বাক্ষর পরীক্ষার আগেই থেমেছে। none বা যেকোনো অচেনা মান একই লাইনে আটকায়, কারণ পরীক্ষাটি “এটি কি অনুমোদিত?”, “এটি কী?” নয়। আসল কোডে ভাঙা token-এর exception ধরে সেটিকেও বাতিল করতে হয়, আর aud তালিকা হলে তার ভেতরে খুঁজতে হয়।

৭ · Revocation, ছোট access token আর refresh rotation

গেট পাসের সমস্যায় ফিরি। কর্মী চাকরি ছেড়ে গেলেন, কিন্তু তাঁর পাসের মেয়াদ আরও ত্রিশ দিন। দারোয়ান সিল দেখে ঢুকতে দেবেন, কারণ তাঁর কোনো খাতা নেই। JWT-র এটিই revocation সমস্যা: যাচাই যদি শুধু স্বাক্ষর আর সময়ের ওপর চলে, তাহলে মাঝপথে বাতিল করার কোনো জায়গা থাকে না।

পথ তিনটি। প্রতি request-এ একটি denylist দেখা, তবে তখন “store লাগে না” দাবিটি আর থাকে না। OWASP বলে তালিকা রাখলে jti আর iss দিয়ে রাখতে, পুরো token বা তার hash দিয়ে নয়। অথবা মেয়াদ খুব ছোট করা। তৃতীয় পথটি বহুল প্রচলিত, দুই token-এর নকশা:

Access token

Access token প্রতিটি API request-এ যায়, মেয়াদ মিনিটের ঘরে, সাধারণত ৫–১৫ মিনিট। ফাঁস হলেও ক্ষতির সময় ছোট।

Refresh token

Refresh token শুধু auth server-এ যায়, নতুন access token আনতে। মেয়াদ বেশি, তাই এটি server-এর খাতায় থাকে, মানে বাতিল করা যায়।

ফলে বাতিলের সীমা নেমে আসে access token-এর মেয়াদে। Refresh token বাতিল করলে নতুন access token আর আসবে না, হাতে থাকা token বড়জোর আর কয়েক মিনিট চলবে। Logout-এর সততা এই কয়েক মিনিটের সমান। বেশি ঝুঁকির কাজে তাই server-side যাচাই বা token introspection রাখা হয়।

Rotation আর reuse detection

Refresh token দীর্ঘজীবী, তাই সে আকর্ষণীয় লক্ষ্য। Refresh token rotation-এ প্রতিটি refresh token একবারই চলে। ব্যবহার করলেই নতুন একটি আসে, পুরোনোটি বাতিল। একই login থেকে জন্ম নেওয়া সব token মিলে একটি token family. RFC 9700 (২০২৫, OAuth 2.0 Security Best Current Practice) ব্যাখ্যা করে: বাতিল হওয়া token যদি আবার আসে, server বুঝতে পারে কিছু গোলমাল, কিন্তু বুঝতে পারে না কে আসল গ্রাহক। তাই সে সক্রিয় refresh token বাতিল করে, আর ব্যবহারকারীকে আবার login করতে হয়। একই RFC বলে, public client-এর refresh token হয় sender-constrained হবে, নয় rotation ব্যবহার করবে।

1row = lookup(token)2if family_revoked(row): 4013if row.used:4  revoke(family); alert()5row.used = True6return new_token(family)
phone family
rt-02ff15
rt-fa169e
rt-b2f38b
family
  1. Login. ফোন পেল প্রথম refresh token rt-02ff15. একটি নতুন family শুরু, নাম phone.
  2. প্রথম rotation. Access token-এর মেয়াদ শেষে অ্যাপ rt-02ff15 পাঠাল। সেটি ব্যবহৃত হলো, নতুন এল rt-fa169e.
  3. দ্বিতীয় rotation. একইভাবে rt-fa169e গেল, এল rt-b2f38b. Family-তে এখন সক্রিয় token একটিই।
  4. পুরোনো token আবার এল। কোনো একটি উৎস থেকে rt-02ff15 ফিরে এসেছে, যা আগেই ব্যবহার হয়েছে। Server জানে না কে পাঠাল। এটি নেটওয়ার্কের ভুল-পুনরাবৃত্তিও হতে পারে, চুরিও হতে পারে।
  5. পুরো family বাতিল। কে আসল তা না জেনেও নিরাপদ সিদ্ধান্ত একটাই: সক্রিয় rt-b2f38b-সহ পুরো family বন্ধ। সঙ্গে নিরাপত্তা-log আর সতর্কবার্তা।
  6. আবার login. ফোন rt-b2f38b পাঠিয়ে পেল 401 family revoked. ব্যবহারকারী নতুন করে login করবেন। অন্য device-এর family অক্ষত থাকে। ইস্যু হওয়া access token তার মেয়াদ পর্যন্ত চলতে পারে।

একই যুক্তি খেলনা কোডে। Token-গুলো স্টেপারের মানের সঙ্গে মিলবে, কারণ seed একই।

// খেলনা refresh server: token real নয়, শুধু ধারণার জন্য
function mulberry32(a) { return () => { a = a + 0x6D2B79F5 | 0;
  let t = Math.imul(a ^ a >>> 15, 1 | a);
  t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
  return ((t ^ t >>> 14) >>> 0) / 4294967296; }; }
const rnd = mulberry32(7);
const tokens = new Map();    // token -> {family, used}
const revoked = new Set();

function issue(family) {
  const t = "rt-" + Math.floor(rnd() * 2 ** 24).toString(16).padStart(6, "0");
  tokens.set(t, { family, used: false });
  return t;
}
function refresh(t) {
  const row = tokens.get(t);
  if (!row) return { status: "401 unknown" };
  if (revoked.has(row.family)) return { status: "401 family revoked" };
  if (row.used) {
    revoked.add(row.family);
    return { status: "401 REUSE, revoke " + row.family };
  }
  row.used = true;
  return { status: "200 rotated", next: issue(row.family) };
}
const show = (who, t, r = refresh(t)) =>
  (console.log(who.padEnd(8), t, "->", r.status, r.next || ""), r.next);
const r1 = issue("phone");
const lap = issue("laptop");
const r2 = show("phone", r1);
const r3 = show("phone", r2);
show("old copy", r1);        // আগেই ব্যবহার হওয়া token আবার এল
show("phone", r3);           // পুরো family বন্ধ
show("laptop", lap);         // অন্য device-এর family অক্ষত

প্রথম দুই লাইন স্বাভাবিক: rt-02ff15 -> 200 rotated rt-fa169e, তারপর rt-fa169e -> 200 rotated rt-b2f38b. তৃতীয় লাইনে old copy rt-02ff15 -> 401 REUSE, revoke phone. এরপর সৎ ফোনটিও পায় rt-b2f38b -> 401 family revoked. এই অসুবিধাটুকু ইচ্ছাকৃত, নিরাপদ পথে ব্যর্থ হওয়া, পর্ব ৩-এর fail secure. শেষে laptop rt-0fdc7f -> 200 rotated rt-857d6f: অন্য family-র ক্ষতি হয়নি। আসল সিস্টেমে store-এ token-এর hash থাকে, কাঁচা token নয়। আর দুর্বল নেটওয়ার্কে উত্তর হারিয়ে গেলে একই token দুবার আসতে পারে, তাই কিছু সিস্টেম খুব ছোট ছাড় রাখে। সেটি নিরাপত্তা আর সুবিধার আপস, ঠিক করতে হয় জেনেবুঝে।

৮ · Browser-এ কোথায় রাখবেন, আর opaque না JWT

এই প্রশ্নে “সম্পূর্ণ নিরাপদ জায়গা” বলে কিছু নেই, শুধু ভিন্ন ঝুঁকি। তুলনাটি দেখুন।

জায়গাScript পড়তে পারে?নিজে থেকে যায়?মূল ঝুঁকি আর প্রতিরক্ষা
HttpOnly cookieনাহ্যাঁCSRF: SameSite আর CSRF token দিয়ে সামলানো হয় (পর্ব ৪১)
localStorageহ্যাঁনাXSS পুরোটা পড়তে পারে, browser বন্ধেও থাকে। OWASP নিষেধ করে
sessionStorageহ্যাঁনাTab বন্ধে যায়, কিন্তু XSS-এর ঝুঁকি একই। OWASP নিষেধ করে
JavaScript memoryচলমান script পারেনাReload-এ হারায়; ছোট মেয়াদের access token-এর জন্য চলে
BFFToken browser-এ আসেই নাSession cookie যায়Token থাকে server-এ; নকশা ভারী, কিন্তু ঝুঁকি সবচেয়ে কম

OWASP Session Management Cheat Sheet-এর অবস্থান পরিষ্কার: session ID, JWT বা refresh token web storage-এ নয়; পছন্দ HttpOnly; Secure; SameSite cookie অথবা Backend-for-Frontend. JavaScript কোর্সের web storage পর্ব এই API-গুলোর সাধারণ ব্যবহার দেখায়, আর web security পর্ব browser-এর দিকটি। মনে রাখুন, XSS থাকলে কোনো জায়গাই পুরো রক্ষা করে না। HttpOnly শুধু token বাইরে নিয়ে যাওয়া আটকায়, যা তবু বড় লাভ: হামলার সময় পাতা খোলা থাকার মধ্যে সীমিত হয়।

Opaque token, নাকি JWT?

Opaque token হলো অর্থহীন এলোমেলো মান, session ID-র মতোই। যাচাই হয় store বা issuer-এর কাছে জিজ্ঞেস করে।

প্রশ্নOpaque বা server sessionJWT
বাতিল করাসঙ্গে সঙ্গে, সারি মুছলেইকঠিন; ছোট মেয়াদ বা denylist লাগে
যাচাইয়ের খরচপ্রতি request-এ একটি lookupStore ছাড়াই, শুধু স্বাক্ষর
নির্ভরতাStore বিকল মানে login বিকলKey জানা থাকলে নিজে চলে
তথ্যের গোপনীয়তাToken-এ কিছু নেইClaim সবাই পড়তে পারে
আকারছোটবড়, প্রতি request-এ যায়
ভুলের দামID দুর্বল হলে অনুমানের ঝুঁকিযাচাইয়ের ভুলে জাল token গৃহীত

সহজ সিদ্ধান্ত: একটি সাধারণ web app, যেখানে login থেকে পাতা একই সিস্টেমে, সেখানে server-side session-ই সঠিক। অনেক service একই token স্বাধীনভাবে যাচাই করবে, বা বাইরের issuer আছে, তখন ছোট মেয়াদের JWT মানায়। অনেক সিস্টেমে দুটোই থাকে: বাইরে opaque, ভেতরে gateway সেটিকে ছোট JWT-তে বদলে দেয়। “JWT আধুনিক” কোনো যুক্তি নয়। প্রশ্ন হলো, আপনার store-এর দাম কি revocation-এর দামের চেয়ে বেশি?

৯ · চুরির সংকেত, step-up আর সাড়া

প্রতিরোধ শতভাগ হয় না। ফোনের ম্যালওয়্যার বা ভুলে শেয়ার করা debug ফাইল থেকেও session বেরিয়ে যেতে পারে। Bearer token-এ server তফাত করতে পারে না, তাই আচরণ দেখতে হয়।

২০২৩ সালের দুটি প্রকাশিত ঘটনা শিক্ষণীয়। CircleCI-এর রিপোর্ট অনুযায়ী, এক প্রকৌশলীর laptop-এর malware একটি 2FA-সমর্থিত SSO session-এর cookie হাতিয়ে নেয়। MFA ঠিকই ছিল, কিন্তু login-এর পরের session-ই পথ হয়ে দাঁড়ায়। Okta জানায়, তাদের support সিস্টেমে গ্রাহকদের আপলোড করা HAR ফাইলে session token ছিল। পরে তারা admin session-কে network location-এ বাঁধে আর HAR থেকে গোপন তথ্য মুছে শেয়ার করতে বলে। শিক্ষা হলো, debug ফাইল আর log-ও token-এর জায়গা, আর admin session-এ বাড়তি শর্ত দরকার।

কোন সংকেত দেখবেন

  • Refresh token reuse: সবচেয়ে শক্ত সংকেত, প্রায় সবসময় তদন্তযোগ্য।
  • একই session-এ হঠাৎ পরিবেশ বদল: দূরের দেশ থেকে IP, ভিন্ন browser পরিচয়, একসঙ্গে দুই জায়গা থেকে ব্যবহার।
  • অচেনা ID-র ঢেউ: একই উৎস থেকে অনেক ভুল session ID বা নকল স্বাক্ষরের token. এটি অনুমান বা ভুল client-এর সংকেত।
  • স্বাক্ষর-ব্যর্থতা হঠাৎ বেড়ে যাওয়া: ভুল key রোল-আউট, নয়তো নকল token পরীক্ষা, দুটোই দেখার মতো।
  • Session-এর পরেই সংবেদনশীল কাজ: email বদল, নতুন payout account, API key তৈরি।

একটি সতর্কতা। বাংলাদেশে মোবাইল ডেটায় অনেকে একই IP ভাগ করেন, আর IP ঘন ঘন বদলায়। তাই IP বদল মানেই চুরি নয়। OWASP-ও একে সংকেত হিসেবে দেখে, নিশ্চিত প্রমাণ হিসেবে নয়। IP-তে session শক্ত করে বাঁধলে সৎ ব্যবহারকারী বারবার ছিটকে পড়বেন। সংকেত এলে সরাসরি শাস্তি না দিয়ে আগে একটি প্রমাণ চান। সেটিই step-up.

Step-up authentication

Step-up authentication মানে সংবেদনশীল কাজের ঠিক আগে আবার প্রমাণ চাওয়া, session যত পুরোনোই হোক। ব্যাংকের অ্যাপে আগেই লগইন করা থাকলেও টাকা পাঠাতে PIN চাওয়া হয়, মোবাইল ব্যাংকিংয়ে সবার পরিচিত দৃশ্য। Password বা email বদল, payout বদল, MFA সরানো, admin কাজ, এসব জায়গায় নিয়মিত step-up রাখুন। সম্ভব হলে phishing-প্রতিরোধী passkey ব্যবহার করুন (পর্ব ১৬)।

Log আর সাড়া

Session-এর জীবনচক্র log করুন: তৈরি, ID বদল, timeout, logout, reuse. কাঁচা token নয়। নিচের উদাহরণটি একটি Sigma-ধরনের নিয়ম। আপনার auth service-এর নিজের log ধরে লেখা, field-এর নাম উদাহরণমাত্র।

title: Refresh token reuse detected
status: experimental
logsource:
  product: example-auth-service
  category: application
detection:
  selection:
    event_action: refresh_token_reuse
  condition: selection
level: high

সতর্কতা এলে সাড়াটি আগে ঠিক করা থাকে: সেই ব্যবহারকারীর সব family বাতিল, সব session শেষ, প্রয়োজনে password reset, ঘটনার সময়ের কাজ পর্যালোচনা, ব্যবহারকারীকে জানানো। স্বাক্ষরের key ফাঁসের সন্দেহ হলে key rotate করতে হয়, আর সেই key-তে দেওয়া সব token বাতিল বলে ধরতে হয়। এজন্যই kid আর একাধিক key রাখার পরিকল্পনা আগে থেকে দরকার। Log আর সাড়ার বিস্তারিত পর্ব ৫৫ ও পর্ব ৬১-তে।

আরও গভীরে: RFC 9068 (২০২১) JWT access token-এর প্রোফাইল দেয়, আর RFC 8725 explicit typ ব্যবহারে জোর দেয়, যাতে এক ধরনের token অন্য ধরনের জায়গায় না চলে। Bearer-এর দুর্বলতা কমাতে DPoP (RFC 9449, ২০২৩) token-কে client-এর key-এর সঙ্গে বাঁধে। Browser cookie-র জন্য W3C-তে Device Bound Session Credentials-এর খসড়া চলছে, আর কিছু browser এটি আনতে শুরু করেছে। সমর্থন ভিন্ন, এবং খসড়া নিজেই বলে device-এ বসে থাকা আক্রমণকারীর সাময়িক ব্যবহার এটি ঠেকায় না।

পরীক্ষা ও ইন্টারভিউতে:

  • Login-এর পর session ID কেন বদলান? Privilege বদলের সময় পুরোনো ID বাতিল করলে session fixation কাজ করে না।
  • JWT আর session-এর মূল পার্থক্য? State কোথায় থাকে: session-এ server-এ, JWT-তে token-এর ভেতরে; তাই JWT বাতিল করা কঠিন।
  • JWT কি encrypted? সাধারণ JWS নয়। Base64url যে কেউ পড়তে পারে, স্বাক্ষর শুধু বদলানো ধরে।
  • Verifier কীভাবে algorithm বাছবে? নিজের কোডের স্থির তালিকা থেকে, token-এর header দেখে নয়।
  • Idle আর absolute timeout কেন দুটোই? Idle ফেলে রাখা session ধরে, absolute চলমান session-এরও শেষ সীমা দেয়।

১০ · AI-এর যুগে session আর token কোড যাচাই

“Express-এ JWT login লিখে দিন” বললে AI কয়েক সেকেন্ডে চলমান কোড দেয়। চলা আর নিরাপদ থাকা এক কথা নয়। এই বিষয়ে AI-র কিছু ভুল বারবার দেখা যায়।

AI যা লিখতে পারেকেন বিপজ্জনকযা চাইবেন
Verify-র বদলে শুধু decode, বা verify বন্ধ করে error সরানোস্বাক্ষর যাচাই-ই হয় নাVerify, সঙ্গে algorithm তালিকা, iss, aud
Key হিসেবে ছোট লেখা, কোডের ভেতরেKey অনুমানযোগ্য, repository-তে ফাঁসCSPRNG-এর ২৫৬ bit, secret store-এ
৩০ দিনের access tokenবাতিল করার উপায় নেইছোট মেয়াদ আর rotation
Token localStorage-এXSS হলে পুরোটা পড়া যায়HttpOnly cookie বা BFF
Logout মানে client-এ token মোছাServer-এর কাছে সবই বৈধServer-এ session বা family বাতিল
CORS সমস্যায় সব origin খুলে দেওয়াCredential-সহ অনুরোধের পথ বড় হয়নির্দিষ্ট origin-এর তালিকা
বানানো RFC নম্বর বা পুরোনো নির্দেশনাভুল আত্মবিশ্বাসRFC বা OWASP-এর মূল পাতা নিজে পড়া

AI-কে লিখতে নয়, পর্যালোচনা করতে বলুন। আসল key, cookie বা token কখনো দেবেন না। নকল মান বসিয়ে দিন।

তুমি একজন application security reviewer. আমার নিজের প্রজেক্টের session আর JWT কোড নিচে দিলাম। গোপন মানগুলো example-token দিয়ে বদলে দিয়েছি। [এখানে নিজের কোড, secret ছাড়া] এই তালিকা ধরে সহজ বাংলায় যাচাই করো: ১. algorithm কি কোডে স্থির? none বা header-নির্ভর বাছাই আছে কি? ২. iss, aud, exp কি সত্যিই যাচাই হচ্ছে? ৩. login-এর পরে session ID বা token কি বদলায়? ৪. cookie-তে Secure, HttpOnly, SameSite, __Host- আছে কি? ৫. logout কি server-এ session বা refresh token বাতিল করে? ৬. refresh rotation আর reuse detection আছে কি? প্রতিটি উত্তরে কোডের লাইন দেখাও, কোন সূত্র (RFC 8725, RFC 9700, OWASP) তা বলো। নিশ্চিত না হলে "নিশ্চিত নই" লেখো। RFC নম্বর বানিও না। শুধু প্রতিরক্ষার পরিবর্তন প্রস্তাব করো।

AI-এর লেখা auth কোড হাতে পেলে

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন, তারপর “→ উত্তর” চাপুন।

প্র ০১Cookie-তে Secure flag কেন এত গুরুত্বপূর্ণ হলো? এত বছর আগেও তো HTTPS ছিল।

পুরোনো দিনের ওয়েবে অনেক বড় সাইট শুধু login পাতা HTTPS-এ রাখত। Password সুরক্ষিত থাকত, কিন্তু login-এর পর বাকি সাইট চলত সাধারণ HTTP-তে, কারণ তখন TLS-কে ধীর আর দামি মনে করা হতো। ফলে session cookie প্রতি request-এ খোলা অবস্থায় যেত।

২০১০ সালে Firesheep নামে একটি Firefox extension প্রকাশিত হয়। এটি উন্মুক্ত Wi-Fi-তে খোলা cookie-র সমস্যাটি সবার সামনে নিয়ে আসে, এত সহজভাবে যে অ-প্রযুক্তিগত মানুষও বিষয়টি বুঝে ফেলেন। এটি নতুন ত্রুটি ছিল না, নিরাপত্তা জগতে সমস্যাটি আগে থেকেই জানা ছিল। নতুন ছিল জনসচেতনতা। এরপর বড় সাইটগুলো পুরো সাইট HTTPS-এ নিতে শুরু করে।

এই ঘটনার শিক্ষা তিনটি। প্রথমত, password রক্ষা করে session না রক্ষা করা অর্ধেক কাজ, কারণ cookie-ই login-এর পরের password. দ্বিতীয়ত, Secure ছাড়া একটিমাত্র HTTP লিংক বা পুরোনো bookmark থেকেও cookie খোলা পথে যেতে পারে, যদিও সাইট HTTPS-এ চলে। তাই পুরো সাইট HTTPS, Secure flag আর পর্ব ১২-এর HSTS, তিনটি একসঙ্গে দরকার। তৃতীয়ত, খরচের ভয় প্রায়ই পুরোনো হিসাবের ওপর দাঁড়িয়ে থাকে। ২০১০ সালের দিকে Google জানায়, Gmail-এর জন্য পুরো সময় HTTPS চালু করতে তাদের CPU খরচ খুব সামান্য বেড়েছে। আধুনিক TLS 1.3-এ সেই খরচ আরও কম।

আজ বাংলাদেশের অনেক ক্যাফে, হোটেল আর বাসের Wi-Fi-তে HTTPS-ই আপনাকে রক্ষা করে। তবু একটি কথা মনে রাখুন, Secure শুধু পথের সুরক্ষা। Device-এর ভেতরের ম্যালওয়্যারের সামনে এটি কিছুই করে না।

মূল উপলব্ধি: প্রতিটি flag একটি নির্দিষ্ট ঐতিহাসিক সমস্যার উত্তর। সমস্যাটি জানলে আপনি বুঝবেন flag কী থামায়, আর কোথায় তার সীমা শেষ।

প্র ০২JWT-র header নিজেই বলে দেয় কোন algorithm, এই নকশা কি ভুল ছিল? none আর algorithm confusion থেকে কী শিখব?

JOSE পরিবারের standard-গুলো (JWS, JWE, JWA, JWT, ২০১৫) নমনীয়তার জন্য বানানো হয়েছিল। alg ক্ষেত্রটি থাকায় নতুন algorithm আনা সহজ, পুরোনোটি সরানো সহজ। এটি পর্ব ১৪-এর crypto agility-র একটি রূপ। Standard বলেনি যে verifier অন্ধভাবে alg মানবে। কিন্তু একটি সুবিধাজনক library API বানাতে গিয়ে অনেকেই ঠিক সেটি করেছিলেন: verify(token, key), আর algorithm পড়া হতো token থেকে।

২০১৫ সালের প্রকাশিত বিশ্লেষণে এই ভুল সামনে আসে। সমস্যার মূল হলো, যাচাই হওয়ার আগের ডেটা ঠিক করছিল যাচাই কীভাবে হবে। নিরাপত্তায় এটি বারবার ফিরে আসা ভুল। TLS-এর downgrade সমস্যাও একই পরিবারের। একই শিক্ষা পর্ব ৩-এর fail-safe defaults থেকেও আসে: অনুমতি থাকবে স্পষ্ট তালিকায়, মেলেনি মানে না।

এরপর দুই ধরনের সাড়া আসে। একটি হলো সংশোধন: লাইব্রেরিগুলো none ডিফল্টে বন্ধ করে, algorithm তালিকা বাধ্যতামূলক করে, আর ২০২০ সালের RFC 8725 নিয়ম লিখে দেয়। আরেকটি হলো পুনর্নকশা: PASETO-র মতো বিকল্প প্রস্তাব বলে, version-ই algorithm ঠিক করবে, ব্যবহারকারীর হাতে পছন্দই থাকবে না। Agility আর ভুল-প্রতিরোধের মধ্যে এটি একটি সত্যিকারের trade-off.

আপনার কাজের জন্য ব্যবহারিক কথা হলো, শুধু “library নিয়েছি” যথেষ্ট নয়। আপনি পরীক্ষা লিখবেন: স্বাক্ষরহীন token, ভুল alg, বদলানো payload, সব বাতিল হচ্ছে কি না। OWASP-ও বলে, recent library-তে এটি ডিফল্টে বন্ধ থাকলেও নিজে যাচাই করে নিতে। এই পরীক্ষা নিজের system-এ, নিজের test key দিয়ে।

মূল উপলব্ধি: যাচাইয়ের নিয়ম কখনো যাচাই-না-হওয়া ডেটা থেকে আসবে না। এই এক লাইন মনে রাখলে JWT ছাড়াও বহু জায়গায় ভুল এড়ানো যায়।

প্র ০৩“JWT মানে stateless, তাই database লাগে না”, এই দাবি বাস্তবে কতটা সত্য?

দাবিটির একটি সত্য অংশ আছে। একটি API শুধু public key দিয়ে token যাচাই করতে পারে, কোনো database না ডেকে। অনেক service-এর জগতে এই স্বাধীনতার মূল্য বড়: প্রতি request-এ একটি কেন্দ্রীয় store ডাকলে সেটি বাধা আর একক ব্যর্থতার বিন্দু হয়।

কিন্তু একটি বাস্তব প্রোডাক্টের চাহিদা শুনুন। ব্যবহারকারী logout করলে সঙ্গে সঙ্গে বন্ধ হোক। হারানো ফোন দূর থেকে বের করে দেওয়া যাক। Password বদলালে অন্য সব device বের হোক। চাকরি ছাড়লে admin-এর access এখনই বন্ধ হোক। প্রতিটি কথার মানে, server-এর কোথাও একটি অবস্থা থাকতে হবে। ফলে refresh token-এর খাতা আসে, বা denylist আসে। তখন আপনি একটি session store-ই বানালেন, শুধু নাম আলাদা, আর সঙ্গে JWT-র ঝুঁকিগুলোও বহন করছেন।

আসলে stateless যাচাই সমস্যাটি দূর করে না, সরিয়ে নেয়। প্রশ্নটি দাঁড়ায়, “কত সময়ের জন্য পুরোনো সিদ্ধান্ত মেনে নিতে রাজি?” ১০ মিনিটের access token মানে, এই সিদ্ধান্ত বদলাতে সর্বোচ্চ ১০ মিনিট লাগতে পারে। অনলাইন খবরের সাইটে এটি কোনো সমস্যা নয়। মোবাইল ব্যাংকিং বা হাসপাতালের রেকর্ডে এটি হয়তো অনেক। NIST SP 800-63B-4-ও স্পষ্ট বলে, access token থাকা মানে ব্যবহারকারী উপস্থিত, এমন ধরে নেওয়া যাবে না।

আবার CAP-ধরনের trade-off-ও মনে রাখুন। Store-নির্ভর যাচাইয়ে store বিকল হলে login বিকল। Stateless যাচাইয়ে সিস্টেম চলতে থাকে, কিন্তু বাতিলের খবর দেরিতে পৌঁছায়। কোনটি বেশি ক্ষতিকর, সেটি ব্যবসার সিদ্ধান্ত, শুধু প্রযুক্তির নয়। একটি ছোট web app-এ, যেখানে একটি database আগে থেকেই আছে, একটি সারি বেশি দেখা প্রায় কোনো খরচই নয়।

মূল উপলব্ধি: State কখনো উবে যায় না। সে হয় আপনার store-এ থাকে, নয় token-এর মেয়াদের ভেতর একটি অপেক্ষার সময় হয়ে থাকে। আপনি শুধু বেছে নেন কোন দাম দেবেন।

প্র ০৪Cookie, না localStorage? দুই পক্ষের বিতর্ক থেকে কী সিদ্ধান্ত নেওয়া যায়?

এই বিতর্কের মূলে দুটি ভিন্ন ঝুঁকি। Cookie নিজে থেকে যায়, তাই CSRF-এর ঝুঁকি আছে। localStorage-এ রাখলে JavaScript নিজে header-এ বসায়, ফলে CSRF প্রায় থাকে না, কিন্তু পাতার যেকোনো script token পড়তে পারে। তাই দুই পক্ষই ঠিক, শুধু ভিন্ন বিপদের কথা বলছে।

তাহলে কোন বিপদের ওজন বেশি? প্রথমত, আধুনিক browser-এ SameSite CSRF-এর পথ অনেকটা ছোট করেছে, আর CSRF token দিয়ে বাকিটা সামলানো যায়। দ্বিতীয়ত, XSS-এ ক্ষতির ধরন আলাদা। HttpOnly cookie থাকলে injected script পাতা খোলা থাকা পর্যন্ত request পাঠাতে পারে, কিন্তু দীর্ঘজীবী token বাইরে নিয়ে যেতে পারে না। localStorage-এ token নিয়ে যেতে পারলে সেটি অন্য কোথাও, পরে, মেয়াদ পর্যন্ত ব্যবহার করা সম্ভব। ক্ষতির সময় আর জায়গা দুটোই অনেক বড়। আধুনিক অ্যাপে হাজারো npm dependency আর তৃতীয় পক্ষের script চলে, তাই পর্ব ৪৮-এর supply chain-এর ঝুঁকিও এই হিসাবে ঢোকে।

তাই OWASP-এর Session Management Cheat Sheet web storage-এ token রাখতে নিষেধ করে, আর IETF-এর browser-based app-সংক্রান্ত আলোচনাও BFF-কে সবচেয়ে নিরাপদ বিকল্প হিসেবে দেখে। BFF-এ browser শুধু একটি HttpOnly session cookie রাখে, আর OAuth token থাকে ছোট একটি server-এ।

বাস্তবে সিদ্ধান্ত এমন হয়। একই domain-এর সাধারণ web app: HttpOnly cookie, CSRF প্রতিরক্ষাসহ। আলাদা API-র SPA: সম্ভব হলে BFF; না হলে ছোট মেয়াদের access token memory-তে, আর refresh token HttpOnly cookie-তে। Mobile অ্যাপ: browser storage নয়, OS-এর নিরাপদ ভাণ্ডার, যেমন Keychain বা Keystore. আর সব ক্ষেত্রেই CSP আর output encoding, কারণ XSS থাকলে শেষ পর্যন্ত কোনো জায়গাই পুরো রক্ষা করে না।

মূল উপলব্ধি: “কোথায় রাখব” প্রশ্নের উত্তর দেয় “কোন ব্যর্থতায় কতটা ক্ষতি”। লক্ষ্য শূন্য ঝুঁকি নয়, ক্ষতির সীমা ছোট রাখা।

প্র ০৫MFA থাকলেও session চুরি কেন এত বড় সমস্যা? IP-তে বেঁধে দিলেই কি সমাধান?

MFA পরীক্ষা করে login-এর মুহূর্তে আপনি কে। এরপর server একটি bearer token দেয়, যা আর কোনো প্রমাণ চায় না। অর্থাৎ MFA যত শক্তই হোক, সেটি দরজার তালা। দরজা খোলার পরের চাবিটি সাধারণ cookie. ২০২৩ সালের CircleCI-র প্রকাশিত রিপোর্টে এই ছবিটিই দেখা যায়: কর্মীর laptop-এ malware, antivirus ধরতে পারেনি, আর 2FA-সমর্থিত SSO session হাতছাড়া। রিপোর্ট অনুযায়ী এরপর তারা production-এ পৌঁছানো কর্মীদের জন্য step-up যোগ করে, আর বিপুল সংখ্যক গ্রাহককে secret বদলাতে বলতে হয়। একটি session-এর দাম কত বড় হতে পারে, এখানেই বোঝা যায়।

IP-তে বাঁধা স্বাভাবিক ভাবনা, আর কিছু ক্ষেত্রে কাজের। Okta ২০২৩ সালের ঘটনার পর admin session-কে network location-এ বেঁধেছে। অফিসের নির্দিষ্ট network থেকে চলা admin-এর জন্য এটি যুক্তিসঙ্গত। কিন্তু সাধারণ গ্রাহকের ক্ষেত্রে এটি ভাঙে। মোবাইল ডেটায় অনেকে একই বহির্গামী IP ভাগ করেন, ফোন Wi-Fi আর ডেটার মধ্যে ঘোরে, IP ঘন ঘন বদলায়। ফলে সৎ মানুষ বারবার বের হবেন, অথচ একই NAT-এর পেছনের কেউ পার পেয়ে যেতে পারেন। OWASP তাই একে সংকেত বলে, প্রতিরক্ষা নয়।

তাহলে পথ কী? স্তরে স্তরে কাজ, পর্ব ৩-এর defense in depth অনুযায়ী। সময়ের সীমা: ছোট session, ছোট token. কাজের সীমা: সংবেদনশীল কাজে step-up, যাতে শুধু cookie দিয়ে টাকা বা account সরানো না যায়। Device-এ বাঁধা: DPoP, mTLS, আর browser-এ Device Bound Session Credentials-এর মতো নতুন প্রচেষ্টা, যেখানে একটি key device-এর হার্ডওয়্যার ছেড়ে বের হয় না। আচরণ দেখা: সংকেত, log আর দ্রুত বাতিল। Endpoint সুরক্ষা: পর্ব ২৯. ডেটা সুরক্ষা: HAR আর debug ফাইল থেকে token মুছে শেয়ার করা।

মূল উপলব্ধি: Authentication একটি ঘটনা নয়, একটি চলমান দাবি। Zero trust-এর ভাষায় (পর্ব ৭৪), বিশ্বাস একবার দিয়ে শেষ নয়, প্রতিটি গুরুত্বপূর্ণ কাজে তা আবার অর্জন করতে হয়।

অনুশীলন

হিসাব, ফল অনুমান আর নকশা পর্যালোচনা। পরীক্ষা শুধু নিজের system-এ।

  1. হিসাব: একটি session ID ৩২ hex অক্ষরের, কিন্তু প্রথম ২০ অক্ষর স্থির (server-এর নাম আর তারিখ)। ধরুন r = 1,000 অনুমান প্রতি সেকেন্ডে, আর S = 10,000 বৈধ session. (ক) কার্যকর entropy কত? (খ) গড় সময় E = 2^b / (r × S) কত দিন? (গ) OWASP-এর ন্যূনতম পূরণ হয়? (ঘ) সমাধান কী?

    (ক) এলোমেলো অংশ ৩২ − ২০ = ১২ hex অক্ষর। প্রতি hex অক্ষরে ৪ bit, তাই ১২ × ৪ = ৪৮ bit.

    (খ) 2^48 = 281,474,976,710,656. r × S = 10^7. তাই E ≈ 28,147,498 সেকেন্ড। ৮৬,৪০০ দিয়ে ভাগ করলে প্রায় ৩২৬ দিন.

    (গ) না। ৪৮ bit ৬৪ bit-এর কম। ৩২ অক্ষর দেখতে লম্বা, কিন্তু শক্তি নির্ভর করে এলোমেলো অংশের ওপর।

    (ঘ) পুরো ID CSPRNG থেকে নিন, যেমন ১২৮ bit, যা hex-এ ৩২ অক্ষরই। দৈর্ঘ্য একই, শক্তি অনেক গুণ বেশি। Server-এর নাম বা তারিখ দরকার হলে store-এর সারিতে রাখুন।

  2. ফল অনুমান করুন: একটি store-এ নিয়ম: now − last ≥ 15 হলে idle timeout, তারপর now − created ≥ 60 হলে absolute timeout. সফল request-এ last = now. Timeout হলে সারি মুছে যায়, আর সারি না থাকলে 401 no session. Login t = 0, তারপর request t = 10, 24, 38, 52, 64, 70. প্রতিটির ফল কী? ABSOLUTE না থাকলে t = 64-তে কী হতো?

    t=10: gap 10, মোট 10, 200. t=24: gap 14, 200. t=38: gap 14, 200. t=52: gap 14, মোট 52, 200. t=64: gap 12, idle ঠিক, কিন্তু মোট 64 ≥ 60, তাই 401 absolute timeout, সারি মুছে গেল। t=70: 401 no session.

    Absolute না থাকলে t=64-তে 200 আসত, আর ১৫ মিনিটের কম ফাঁকে কাজ চললে session কখনোই শেষ হতো না। এই কারণেই দুটি ঘড়ি।

  3. নকশা পর্যালোচনা: একটি কাল্পনিক অনলাইন বাজারের নকশা: ১) Set-Cookie: sid=1042-20261031; Domain=example.com; Path=/; SameSite=None ২) JWT verifier token-এর header থেকে algorithm পড়ে ৩) Access token ৩০ দিনের, localStorage-এ ৪) Logout বাটন শুধু client-এ token মোছে ৫) Payload-এ গ্রাহকের NID নম্বর। প্রতিটির সমস্যা আর সমাধান লিখুন।
    • ১: ID অনুমানযোগ্য (user নম্বর আর তারিখ)। Domain সব subdomain-এ পাঠায়। Secure আর HttpOnly নেই, আর SameSite=None সমর্থিত হতে Secure লাগে। সমাধান: __Host-sid নাম, CSPRNG-এর ID, Path=/; Secure; HttpOnly; SameSite=Lax.
    • ২: যাচাই হওয়ার আগের ডেটা নিয়ম ঠিক করছে। সমাধান: কোডে স্থির allowlist, key-এর সঙ্গে algorithm বাঁধা, none কখনো নয়।
    • ৩: ফাঁস হলে ৩০ দিনের ঝুঁকি, XSS পুরোটা পড়তে পারে। সমাধান: ৫–১৫ মিনিটের access token, rotating refresh token, HttpOnly cookie বা BFF.
    • ৪: Server-এর কাছে token বৈধই থাকে। সমাধান: refresh family বাতিল, access token ছোট, device list.
    • ৫: JWT পড়া যায়, তাই NID ফাঁস। Data minimization অনুযায়ী বাদ দিন, দরকারে server-এ রাখুন, পর্ব ৭০-এর privacy নীতিও এখানে প্রযোজ্য।
  4. নিজের কম্পিউটারে কমান্ড: নিচের কমান্ডটি চালান। এটি নিরাপদ, শুধু দৈর্ঘ্য ছাপে, মানটি কোথাও যায় না। তারপর নিজের তৈরি বা নিজের অনুমতিপ্রাপ্ত test সাইট browser-এর DevTools → Application → Cookies-এ খুলে session cookie-র Secure, HttpOnly আর SameSite কলাম দেখুন।
    python -c "import secrets; print(len(secrets.token_urlsafe(32)), len(secrets.token_hex(16)))"

    এই লাইনের ফল সবসময় একই: 43 32. token_urlsafe(32) ৩২ byte, মানে ২৫৬ bit, base64url-এ ৪৩ অক্ষর। token_hex(16) ১৬ byte, মানে ১২৮ bit, hex-এ ৩২ অক্ষর। DevTools-এ কোনো কলাম ফাঁকা থাকলে নিজের config ঠিক করুন, আর Domain কলামে subdomain-ঘেঁষা মান থাকলে কারণ খুঁজুন। আসল cookie-র মান কাউকে দেখাবেন না, স্ক্রিনশটেও নয়।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমএকটি JWT যাচাইয়ের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. Token-কে তিন অংশে ভাঙা
  2. Header-এর alg server-এর allowlist-এ মেলানো
  3. Server-এর key দিয়ে signature যাচাই
  4. iss আর aud মেলানো
  5. exp দেখা
  6. গৃহীত claim নিয়ে authorization-এর সিদ্ধান্ত

Session fixation ঠেকানোর প্রধান উপায় কোনটি?

  • Session ID-র দৈর্ঘ্য দ্বিগুণ করা
  • Login-এর পরে নতুন session ID দেওয়া এবং পুরোনোটি server-এ বাতিল করা
  • Cookie-তে HttpOnly দেওয়া
  • Idle timeout ৫ মিনিট করা

HttpOnly cookie থাকা সত্ত্বেও পাতায় XSS থাকলে কোনটি সত্য?

  • XSS আর কোনো ক্ষতি করতে পারে না
  • Script document.cookie দিয়ে cookie-টি পড়তে পারে
  • Browser এই cookie কোনো request-এই পাঠায় না
  • Script cookie পড়তে পারে না, কিন্তু ব্যবহারকারীর পরিচয়ে request পাঠাতে পারে

একটি সাধারণ স্বাক্ষরিত JWT-র payload-এ গ্রাহকের ফোন নম্বর রাখা হলে কী হয়?

  • Token যাঁর হাতে আছে, তিনি key ছাড়াই নম্বরটি পড়তে পারেন
  • স্বাক্ষরের কারণে নম্বরটি গোপন থাকে
  • শুধু server-এর key দিয়েই decode করা যায়
  • HS256 payload-টি নিজে থেকে encrypt করে

একটি JWT verifier algorithm কীভাবে ঠিক করবে?

  • Token-এর header-এ যা লেখা আছে, তা-ই মেনে
  • যে algorithm-এ সফল হয়, পরপর চেষ্টা করে
  • নিজের কোডের স্থির তালিকা থেকে, প্রতিটি key একটি algorithm-এ বাঁধা রেখে
  • Header-এ none থাকলে যাচাই বাদ দিয়ে

Refresh token rotation চালু আছে। R1 দিয়ে R2 নেওয়া হলো। এরপর R1 আবার auth server-এ এল। নিরাপদ সাড়া কোনটি?

  • R1 গ্রহণ করে আরেকটি নতুন token দেওয়া
  • R2-সহ পুরো family বাতিল করা এবং সতর্কবার্তা তোলা
  • শুধু R1-কে বাতিল করে R2 চালু রাখা
  • ব্যবহারকারীর account চিরতরে বন্ধ করা

একটি session ID ১৬ hex অক্ষরের, কিন্তু প্রথম ৮ অক্ষর সব সময় একই। ধরুন r = 10,000 অনুমান প্রতি সেকেন্ডে, S = 100,000 বৈধ session, আর গড় সময় E = 2^b / (r × S). E মোটামুটি কত?

  • প্রায় ৫৮৫ বছর
  • প্রায় ১০২২ বছর
  • প্রায় ৪.৩ সেকেন্ড
  • এক সেকেন্ডের হাজার ভাগের এক ভাগের কম

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন, অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. Session token login-এর পরের চাবি। ID এলোমেলো, ন্যূনতম ৬৪ bit, login-এর পরে নতুন।
  2. Cookie: __Host-, Secure, HttpOnly, SameSite. Flag নির্দিষ্ট ঝুঁকি কমায়, XSS বা CSRF পুরো দূর করে না।
  3. Timeout আর logout server-এ। Idle আর absolute দুটোই। Cookie মোছা logout নয়, সারি মোছাই logout.
  4. JWT পড়া যায়, বদলানো ধরা পড়ে। Algorithm আপনার তালিকা থেকে, তারপর স্বাক্ষর, iss, aud, exp.
  5. ছোট access token আর rotating refresh token. পুরোনো refresh ফিরলে family বাতিল। Web storage-এ token নয়, সংবেদনশীল কাজে step-up.

পরের পর্বে: পর্ব ১৮-তে দেখবেন OAuth 2.0 আর OpenID Connect: নিজের password না দিয়ে অন্য অ্যাপকে সীমিত অনুমতি দেওয়া, PKCE আর সাধারণ ভুল।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

মূল সূত্র: RFC 7519, RFC 8725, RFC 9700, OWASP Session Management Cheat Sheet, OWASP JSON Web Token Cheat Sheet, NIST SP 800-63B-4, MDN Set-Cookie (সবই ৩১ অক্টোবর ২০২৬ তারিখে মেলানো)।

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান