Authentication & Security

Interview Context

DS/MLE 面試的 system design 環節越來越常出現 auth 題:你的 model API 誰可以呼叫?dashboard 怎麼登入?pipeline 之間怎麼互相信任?面試官想確認你不只會建模,還能安全地把系統接到公司環境裡 — session vs JWT、OAuth flow、SQL injection 防禦是最常被追問的三個主題。

What You Should Understand

  • 能解釋 cookie-based session(server 有狀態)和 token-based auth(stateless)的運作方式與取捨
  • 能拆解 JWT 的 header.payload.signature 結構,說明 HS256 vs RS256、expiry/refresh token、以及為什麼 JWT 很難撤銷
  • 能一步一步講出 OAuth 2.0 authorization code flow,並區分 OAuth(授權)、OIDC(認證)、SSO(單一登入)
  • 知道 API key、bearer token、OAuth client credentials、mTLS、HMAC signature 各自適合的場景
  • 能說明 SQL injection、XSS、CSRF 的攻擊原理與對應防禦(parameterized query、escaping/CSP、SameSite cookie)

Session vs Cookie vs Token

How Cookie-Based Sessions Work

Session auth keeps the login state on the server:

  1. User submits username + password → server verifies credentials.
  2. Server creates a session record(例如存在 Redis 或 database): session ID → user ID, roles, expiry.
  3. Server responds with Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=Lax.
  4. Browser automatically attaches the cookie on every subsequent request to the same domain.
  5. Server looks up the session ID → knows who the user is → serves the request.

直覺:cookie 只是「置物櫃鑰匙」,真正的身分資料放在 server 的置物櫃裡。要登出或封鎖使用者,server 直接刪掉那筆 session record 就好 — 即時撤銷是 session 的最大優勢。

How Token-Based Auth Works

Token auth keeps the login state inside the token itself(stateless):

  1. User logs in → server verifies credentials.
  2. Server signs a token containing identity claims(user ID, roles, expiry)— typically a JWT.
  3. Client stores the token and sends it on each request: Authorization: Bearer eyJhbGci....
  4. Server verifies the signature and reads the claims — no database lookup needed.

直覺:token 是一張「有防偽簽名的通行證」,證件內容都寫在卡片上。任何一台 server 只要有驗證用的 key 就能檢查,不需要共享 session storage — 這讓 token 在分散式系統和跨服務場景特別好用。

Comparison

DimensionCookie-Based SessionToken-Based (JWT)
State locationServer (session store)Client (self-contained token)
Horizontal scalingNeeds shared store (Redis) or sticky sessionsTrivial — any server can verify
RevocationInstant — delete the session recordHard — token valid until expiry
CSRF riskYes — browser auto-sends cookiesLow if sent via Authorization header
XSS riskLow with HttpOnly cookie (JS cannot read it)High if token stored in localStorage
Cross-domain / mobile / APIAwkward — cookies are domain-boundNatural fit
PayloadJust an opaque IDCarries claims (roles, user ID, expiry)
Best forServer-rendered web apps, admin dashboardsAPIs, microservices, mobile clients, SSO

常見誤解:JWT 不是 session 的無腦升級

很多候選人以為「JWT 比較新所以比較好」。面試官期待你講出取捨:JWT 換來 stateless scalability,代價是失去即時撤銷能力、token 一旦外洩在過期前都有效。單一 server 的內部工具用 session 往往更簡單也更安全。

JWT Deep Dive

Anatomy: header.payload.signature

A JWT is three base64url-encoded parts joined by dots:

eyJhbGciOiJIUzI1NiJ9 . eyJzdWIiOiI0MiIsImV4cCI6MTcyMH0 . SflKxwRJSMeKKF2QT4fwpM
        header                    payload                     signature
  • Header: metadata — signing algorithm and token type, e.g. {"alg": "HS256", "typ": "JWT"}.
  • Payload: the claims — statements about the user and the token itself.
  • Signature: cryptographic proof that header + payload have not been tampered with.

For HS256:

signature=HMAC-SHA256(base64url(header)+"."+base64url(payload), secret)\text{signature} = \text{HMAC-SHA256}(\text{base64url(header)} + \text{"."} + \text{base64url(payload)},\ \text{secret})

Encoded 不等於 Encrypted

JWT 的 payload 只是 base64url 編碼,任何人都能解開來讀。簽名只保證「內容沒被竄改」,不保證「內容保密」。絕對不要把密碼、個資、API secret 放進 JWT payload — 這是面試中一句話就能加分(或扣分)的細節。

Standard Claims

ClaimMeaningExample
issIssuer — who created the tokenauth.company.com
subSubject — the user this token is aboutuser-42
audAudience — intended recipient serviceml-api
expExpiration time (Unix timestamp)1720000000
iatIssued at1719996400
nbfNot valid before1719996400
jtiUnique token ID — enables denylisting9f2c...

HS256 vs RS256

AspectHS256 (HMAC + SHA-256)RS256 (RSA + SHA-256)
Key typeSymmetric — one shared secretAsymmetric — private signs, public verifies
Who can signAnyone holding the secretOnly the private key holder
Who can verifyAnyone holding the secret(= 也能簽!)Anyone with the public key
Key distributionSecret must be shared with every verifierPublish public key via JWKS endpoint
SpeedFasterSlower (asymmetric crypto)
Best forSingle service signs and verifies itselfMany services verify tokens from one auth server

直覺:HS256 像「大家共用同一把鑰匙」— 只要一個 verifier 被入侵,攻擊者就能偽造 token。RS256 把「簽發」和「驗證」的能力分開,auth server 私鑰簽名、下游服務用公鑰驗證,這是 microservices 和 OIDC 的標準做法。

Expiry and Refresh Tokens

Standard pattern — short-lived access token + long-lived refresh token:

TokenLifetimeStored WherePurpose
Access token5–15 minutesClient memorySent on every API call
Refresh tokenDays–weeksHttpOnly cookie or secure storage; tracked server-sideExchange for a new access token

Flow: access token expires → client calls the token endpoint with the refresh token → server checks the refresh token(server 端有記錄,可以撤銷)→ issues a new access token. Refresh token rotation 每次換發都作廢舊的 refresh token,如果同一個 refresh token 被用兩次 → 代表外洩 → 整條 token family 全部撤銷。

Why You Cannot Easily Revoke a JWT

Stateless 的代價:server 驗證 JWT 時不查資料庫,所以沒有地方可以標記「這張 token 作廢了」。使用者登出、被停權、token 外洩 — 在 exp 到期之前 token 都持續有效。

Mitigations(每一個都是 tradeoff):

MitigationHowCost
Short expiryAccess token lives 5–15 minNeeds refresh token machinery
DenylistStore revoked jti in Redis, check on each requestReintroduces server state — no longer stateless
Token versioningStore a version number per user; bump to invalidate all tokensOne DB/cache read per request
Rotate signing keyAll tokens die at onceLogs out every user — emergency only

JWT vs PASETO

AspectJWTPASETO
Algorithm choiceHeader declares alg — flexible but dangerousFixed per protocol version — no negotiation
Known footgunsalg: none attack, HS256/RS256 confusion attackDesigned to eliminate those by construction
ModesSigned (JWS) or encrypted (JWE)local(symmetric encrypted), public(asymmetric signed)
EcosystemUbiquitous — every language, OIDC standardSmaller but growing

直覺:JWT 最大的歷史問題是「algorithm agility」— token 自己宣告用什麼演算法驗證,寫壞的 library 曾接受 alg: none(不驗簽名)或把 RS256 公鑰當 HS256 secret 用。PASETO 的哲學是把演算法寫死在協定版本裡,讓開發者沒有機會選錯。面試時能講出這個設計動機就是深度的展現。

OAuth 2.0 & SSO

The Four Roles

RoleWhoExample
Resource OwnerThe user who owns the data
ClientThe app requesting access一個想讀你 Google Calendar 的排程工具
Authorization ServerIssues tokens after consentGoogle 的 OAuth server
Resource ServerHosts the protected data, accepts access tokensGoogle Calendar API

核心觀念:OAuth 2.0 解決的是「委託授權」— 讓第三方 app 拿到一張範圍受限的 access token,而不是把你的密碼交給它。OAuth 本身是 authorization protocol,不是 authentication protocol。

Authorization Code Flow, Step by Step

  1. Redirect to authorize: client 把 user 的瀏覽器導向 authorization server,帶上 client_id, redirect_uri, scope, 和隨機的 state(防 CSRF)。
  2. User authenticates and consents: user 在 auth server 登入(client 永遠看不到密碼),同意授權畫面列出的 scopes。
  3. Redirect back with code: auth server 把瀏覽器導回 redirect_uri,附上一次性的短效 authorization code
  4. Back-channel token exchange: client 的 server 直接向 token endpoint 送出 code + client_secret,換回 access token(有時加上 refresh token)。這步走 server-to-server,token 不經過瀏覽器。
  5. Call the API: client 帶著 Authorization: Bearer access_token 呼叫 resource server。

為什麼要多一步 code exchange?因為瀏覽器 redirect 是「front channel」,URL 可能被 log、被 history 記下來。真正值錢的 access token 只在「back channel」傳遞。Public clients(SPA、mobile app)沒有能力保管 client_secret,所以用 PKCE:client 先送 code challenge(隨機值的 hash),換 token 時出示原始值 — 攔截到 code 的攻擊者換不到 token。

OIDC: Identity on Top of OAuth

OAuth 2.0 只回答「這個 app 可以做什麼」,不回答「這個 user 是誰」。OpenID Connect (OIDC) 在 OAuth 上加了一層身分:

  • 多回傳一個 ID token(一個 JWT)— 內含 sub, iss, aud, exp 等身分 claims。
  • 標準化的 userinfo endpoint 和 discovery document。
  • 「Sign in with Google」就是 OIDC。

How SSO Works: SAML vs OIDC

SSO 的核心:把「認證」集中到一個 Identity Provider (IdP)。App(Service Provider)不自己驗密碼,而是把 user 轉去 IdP;IdP 有全域 session,第二個 app 來的時候不用重新登入,直接發 token/assertion 回去。

AspectSAML 2.0OIDC
FormatXML assertionsJSON + JWT
TransportBrowser POST/redirect bindingsHTTPS redirects + JSON APIs
Era / fit2005 — enterprise web apps2014 — modern web, mobile, APIs
ComplexityHeavy (XML signatures, metadata)Lighter, developer-friendly
Typical IdPOkta, ADFS, Azure ADGoogle, Auth0, Keycloak, Azure AD

實務上:老牌企業內部系統多半接 SAML,新的產品和 API 幾乎都走 OIDC。兩者常常並存在同一個 IdP 上。

Where 2FA Fits In: TOTP Flow

Two-factor authentication 在「密碼驗證成功之後、session/token 簽發之前」插入第二道檢查:

  1. Enrollment: server 產生一個 shared secret,用 QR code 給 authenticator app(Google Authenticator, 1Password)。
  2. Code generation: app 每 30 秒算一次 6 位數 code:
TOTP=Truncate(HMAC-SHA1(secret, unix_time30))\text{TOTP} = \text{Truncate}\left(\text{HMAC-SHA1}\left(\text{secret},\ \left\lfloor \frac{\text{unix\_time}}{30} \right\rfloor\right)\right)
  1. Verification: user 輸入 code → server 用同一個 secret 和目前的 time window 重算比對(通常容忍前後一個 window 的時鐘誤差)→ 通過才建立 session。

SMS OTP 被視為較弱的第二因子(SIM swapping 攻擊),TOTP 或 hardware key(FIDO2/WebAuthn)是面試時該給的答案。

API Authentication Methods

Service 對 service、client 對 API 的認證選項比較:

MethodHow It WorksSecurity LevelBest For
API KeyStatic random string in header; server looks it upLow–medium — long-lived, no user identityServer-to-server, usage tracking, rate limiting per caller
Bearer Token (JWT)Signed token with claims and expiryMedium–high — short-lived, carries identity/rolesUser-facing APIs, microservices
OAuth 2.0 Client CredentialsService exchanges client_id + secret for a scoped, short-lived access tokenHigh — central issuance, rotation, scopes, auditService-to-service in orgs with an auth server
mTLSBoth sides present X.509 certificates during TLS handshakeVery high — identity at transport layerZero-trust networks, service mesh (Istio), banking
HMAC Request SigningClient signs method + path + timestamp + body with a shared secretHigh — integrity + replay protectionWebhooks, payment APIs (AWS SigV4, Stripe style)

幾個面試常追問的差異點:

  • API key vs token:API key 是「長期有效的靜態身分」,通常代表一個 app 而不是一個 user,沒有內建過期與 scope;token(JWT/OAuth)短效、可帶 claims、可縮小權限範圍。Best practice 是 leveled API keys — 不同權限等級發不同的 key。
  • HMAC signing 的獨特價值:它簽的是「整個 request」,所以同時保證 request integrity(body 沒被改)和 anti-replay(timestamp 過期就拒絕)— bearer token 只證明「你有 token」,不保護 request 內容。
  • mTLS 把認證下沉到 TLS 層,application code 完全不用管 token,但憑證的簽發與輪換需要 infrastructure(service mesh 幫你做掉這件事)。

Access Control

Authentication vs Authorization

QuestionTermExample
Who are you?Authentication (AuthN)Login with password + TOTP
What can you do?Authorization (AuthZ)Can this analyst delete the production table?

先 AuthN 後 AuthZ — 順序永遠是「先確認身分,再檢查權限」。401 Unauthorized 其實是 authentication 失敗,403 Forbidden 才是 authorization 失敗,這個 HTTP status 的區分也常被面試官順口一問。

RBAC vs ABAC vs ACL

ModelGrants Access ByExampleProsCons
ACLExplicit list per resourceFile X readable by users A, BSimple, fine-grainedUnmanageable at scale
RBACRoles assigned to users; permissions attached to rolesdata-analyst role can read warehouseEasy to audit, maps to org structureRole explosion for complex rules
ABACPolicy over attributes (user, resource, environment)Allow if user.dept = resource.dept and time is business hoursExtremely flexible, context-awareHard to reason about and audit

實務上 90% 的系統用 RBAC 就夠了;當規則變成「同部門 + 上班時間 + 資料分級 P2 以下」這種多維條件時才升級到 ABAC。

Principle of Least Privilege

每個 user、service、API key 只拿到完成工作所需的最小權限

  • Dashboard 的 DB 帳號只有 SELECT,沒有 DROP — SQL injection 發生時 blast radius 有限。
  • Pipeline 的 service account 只能寫自己的 output bucket。
  • API key 分等級(read-only vs read-write),外洩時損害受控。

這個原則會反覆出現在下面每一種攻擊的防禦裡 — 它不是防止入侵,而是限制入侵後的損害

Common Attacks & Defenses

SQL Injection

攻擊原理:user input 被字串拼接進 SQL,於是 input 裡的 SQL 語法被當成指令執行。

-- Intended query, user_input = "alice"
SELECT * FROM users WHERE name = 'alice';

-- Attacker sends: ' OR '1'='1' --
SELECT * FROM users WHERE name = '' OR '1'='1' --';
-- WHERE clause is always true: returns every row

Defense — parameterized queries(唯一根治的方法):SQL 語句和資料分開傳給 database driver,input 永遠被當成 value,不可能變成語法。輔助防線:ORM(底層就是 parameterized)、least-privilege DB user、input validation、不把 DB error 原文回給 client。

XSS (Cross-Site Scripting)

攻擊原理:攻擊者的 JavaScript 被注入到頁面裡,在受害者的瀏覽器以該網站的身分執行 — 可以偷 cookie、token、竄改頁面。

TypeWhere the Payload LivesExample
StoredSaved in the database, served to every visitorMalicious script in a comment field
ReflectedEchoed back from the requestSearch page prints the query unescaped
DOM-basedNever touches the server — client-side JS writes untrusted data into the DOMinnerHTML = location.hash

Defenses:

  • Output escaping / encoding:render 時把 user content 的特殊字元轉義(modern frameworks like React escape by default)。
  • Content-Security-Policy (CSP):header 白名單限制 script 來源,禁 inline script → 注入的 script 無法執行。
  • HttpOnly cookies:JS 讀不到 session cookie → 就算 XSS 成功也偷不走。

CSRF (Cross-Site Request Forgery)

攻擊原理:瀏覽器對每個 request 自動附上該網域的 cookie。攻擊者的網頁偷偷對 bank.com/transfer 發 POST — 瀏覽器忠實地帶上你的 bank.com session cookie,server 以為是你本人操作。攻擊者不需要偷到 cookie,只需要「借用」它。

Defenses:

  • SameSite cookiesSameSite=Lax(現代瀏覽器預設)讓 cross-site 的 POST 不帶 cookie — 一行設定擋掉大多數 CSRF。
  • CSRF token:server 在表單裡埋一個隨機 token,submit 時驗證 — 攻擊者的網站拿不到這個值。
  • Check Origin/Referer header:拒絕來源不對的 state-changing request。
  • 注意:用 Authorization header 送 token 的 API 天然免疫 CSRF(header 不會被瀏覽器自動附上)— 這是 token-based auth 的一個安全優勢。

Attack → Defense Summary

AttackRoot CausePrimary DefenseSecondary Defenses
SQL InjectionInput concatenated into SQLParameterized queriesORM, least-privilege DB user, input validation
XSSUntrusted data rendered as HTML/JSOutput escapingCSP, HttpOnly cookies, framework auto-escaping
CSRFBrowser auto-sends cookies cross-siteSameSite=Lax/Strict cookiesCSRF tokens, Origin check, use Authorization header
Token theftToken stored where JS can read itHttpOnly cookie or in-memory storageShort expiry, refresh rotation, HTTPS only
Replay attackCaptured request re-sentHMAC signature with timestampNonce tracking, short signature validity

API Security Checklist

上線一個 model API 或 data service 前的實務清單:

ItemWhyHow
HTTPS everywhereTokens and data in plaintext otherwiseTLS 1.2+, redirect HTTP → HTTPS, HSTS header
Auth on every endpointOne forgotten route = open doorMiddleware-level enforcement, deny by default
Rate limitingBrute force, scraping, cost abuseToken bucket per API key/IP, 429 responses
Input validationInjection, malformed payloadsSchema validation (Pydantic), allowlists, size limits
Secrets managementKeys in code leak via gitVault/Secrets Manager, env injection, rotation schedule
Audit loggingDetect abuse, forensics, complianceLog who did what when — never log tokens or passwords
Least-privilege credentialsLimit blast radiusRead-only DB users, scoped tokens, leveled API keys
Dependency scanningKnown CVEs in librariesDependabot, pip-audit in CI

面試加分句

「security 是分層防禦(defense in depth)— 沒有單一措施是完美的,所以 parameterized query 之外還要 least-privilege DB user,HttpOnly 之外還要 CSP。」能自然講出這句話,代表你有 security mindset 而不是背清單。

Real-World Use Cases

Case 1: 內部 ML Dashboard — Session 還是 JWT?

你為 data team 建了一個 Streamlit/Dash dashboard 顯示 model metrics,公司要求加上登入。你會選 session 還是 JWT?

分析:這是單一 server、server-rendered、內部使用者的場景 —

  • Session 勝出:使用者少(不需要 stateless scaling)、需要即時撤銷(員工離職馬上失效)、HttpOnly session cookie 免疫 XSS 偷 token。
  • 更好的答案:不要自己做登入,接公司的 SSO(OIDC)— dashboard 變成 OIDC client,把認證委託給 IdP(Okta/Azure AD),自己只保留一個短效的 local session。員工離職時 IdP 一處停用,全公司系統同步失效。

Interview follow-ups:

  • 如果 dashboard 之後拆成 SPA + API,你的選擇會改變嗎?(API 改用短效 JWT,SPA 用 OIDC + PKCE)
  • Session store 放哪裡?server 重啟會發生什麼事?(in-memory 會全部登出 → 放 Redis)
  • 為什麼 HttpOnly 對這個場景重要?(dashboard 常 render user-generated content,XSS 風險真實存在)

Case 2: Data Pipeline 之間的 Service-to-Service Auth

你的 Airflow DAG 每小時呼叫 feature store API 寫入 features,另外有一個 batch scoring service 讀取。這些 machine-to-machine 呼叫該用 API key 還是 OAuth client credentials?

分析:

  • API key:最簡單 — 發一把 key 給 Airflow,API gateway 驗證。適合小團隊、少量 service。缺點:長期有效、rotation 靠人工、權限粒度粗。
  • OAuth client credentials flow:每個 service 有 client_id + secret,向 auth server 換短效、有 scope 的 access token(例如 feature-store:write)。集中管理、可審計、token 外洩損害只有幾分鐘。適合 service 數量成長的組織。
  • mTLS:如果公司已有 service mesh(Istio/Linkerd),憑證自動輪換,application 層完全不用碰 auth — 但這是 infra 決策,不是 pipeline 團隊自己能選的。

務實的回答:從 leveled API keys 起步(read key vs write key 分開),service 超過一定數量或有 compliance 需求時遷移到 client credentials。

Interview follow-ups:

  • API key 要怎麼 rotate 而不中斷 pipeline?(同時接受新舊兩把 key 的 overlap window)
  • Secret 存在哪裡?(Vault / cloud secrets manager,注入環境變數,絕不進 git)
  • 怎麼發現 key 被濫用?(per-key rate limiting + audit log 上的異常流量告警)

Case 3: SQL 分析工具防注入

你做了一個內部工具:分析師在 UI 選 filter(國家、日期範圍、metric),工具動態組 SQL 查 warehouse。安全風險在哪?

分析:filter 值來自 user input → 直接 f-string 拼進 SQL 就是教科書級的 SQL injection。防禦分三層:

  1. Values 用 parameterized query — 日期、國家名稱這些「值」全部走 placeholder。
  2. Identifiers 用 allowlist — column name 和 table name 不能參數化(SQL 語法限制),所以只能對照白名單:user 選的 metric 必須在 {"revenue", "ctr", "dau"} 這類預先定義的集合裡,否則拒絕。
  3. Least-privilege DB user — 工具的 connection 只有特定 schema 的 SELECT 權限。就算前兩層都失守,攻擊者也 drop 不了 table。

Interview follow-ups:

  • 為什麼 column name 不能用 placeholder?(parameterized query 只能綁定 value,不能綁定 SQL 結構/identifier)
  • ORM 就完全安全嗎?(ORM 的 raw() / string filter 介面一樣可以被注入 — 安全來自 parameterization,不是 ORM 本身)
  • 查詢結果顯示在網頁上,還有什麼風險?(stored XSS — 資料裡若有 script,render 時要 escape)

Hands-on: Auth & Security in Python

JWT Encode / Decode with PyJWT

import jwt
import datetime

SECRET = "load-this-from-a-secrets-manager"  # never hardcode in real code

# Issue a short-lived access token with standard claims
payload = {
    "sub": "user-42",                 # subject: who this token is about
    "role": "analyst",                # custom claim used for authorization
    "iss": "auth.internal",           # issuer
    "aud": "ml-api",                  # intended audience
    "iat": datetime.datetime.now(datetime.timezone.utc),
    "exp": datetime.datetime.now(datetime.timezone.utc)
           + datetime.timedelta(minutes=15),   # short expiry limits damage if leaked
}
token = jwt.encode(payload, SECRET, algorithm="HS256")

# Verify: pin the algorithm and audience explicitly
try:
    claims = jwt.decode(
        token,
        SECRET,
        algorithms=["HS256"],   # never let the token choose its own algorithm
        audience="ml-api",      # reject tokens minted for other services
    )
    user_id = claims["sub"]     # safe to trust after signature check
except jwt.ExpiredSignatureError:
    pass  # token expired: client should use its refresh token
except jwt.InvalidTokenError:
    pass  # tampered, wrong audience, or wrong key: reject with 401

Parameterized SQL vs Vulnerable String Formatting

import sqlite3

conn = sqlite3.connect("analytics.db")
user_input = "alice' OR '1'='1"   # attacker-controlled value

# ANTI-PATTERN (do NOT do this): input becomes part of the SQL syntax
# query = f"SELECT * FROM users WHERE name = '{user_input}'"
# conn.execute(query)   # WHERE is always true: returns every row

# CORRECT: parameterized query keeps SQL and data separate
rows = conn.execute(
    "SELECT * FROM users WHERE name = ?",   # ? is a placeholder, not concatenation
    (user_input,),                          # driver binds this strictly as a value
).fetchall()                                # returns nothing: no user literally named that

# Identifiers (column/table names) cannot be parameterized: use an allowlist
ALLOWED_METRICS = {"revenue", "ctr", "dau"}
metric = "revenue"                          # value chosen in the UI
if metric not in ALLOWED_METRICS:
    raise ValueError("unknown metric")      # reject anything outside the allowlist
rows = conn.execute(
    f"SELECT {metric} FROM daily_stats WHERE day = ?",  # safe: metric was allowlisted
    ("2026-07-01",),
).fetchall()

HMAC Request Signing

import hmac
import hashlib
import time

SHARED_SECRET = b"per-client-secret-from-vault"

def sign_request(method, path, body, timestamp):
    # Sign the whole request: integrity + authenticity in one signature
    message = f"{method}\n{path}\n{timestamp}\n{body}".encode()
    return hmac.new(SHARED_SECRET, message, hashlib.sha256).hexdigest()

# Client side: attach timestamp and signature as headers
ts = str(int(time.time()))
body = '{"model": "fraud-v3", "features": [0.1, 0.9]}'
signature = sign_request("POST", "/v1/score", body, ts)
# send headers: X-Timestamp: ts, X-Signature: signature

# Server side: recompute and compare
def verify_request(method, path, body, ts, received_sig, max_skew=300):
    if abs(time.time() - int(ts)) > max_skew:
        return False                        # stale timestamp: blocks replay attacks
    expected = sign_request(method, path, body, ts)
    # constant-time comparison prevents timing side-channel attacks
    return hmac.compare_digest(expected, received_sig)

Interview Signals

What interviewers listen for:

  • 你能講出 session 和 JWT 的核心 tradeoff(即時撤銷 vs stateless scaling),而不是「JWT 比較新所以比較好」
  • 你知道 JWT payload 只是編碼不是加密,且能解釋為什麼 revocation 困難、有哪些緩解手段
  • 你能一步一步走完 authorization code flow,並說出為什麼 token exchange 要走 back channel
  • 被問攻擊時你先講 root cause 再講防禦:SQL injection 是拼接、CSRF 是 cookie 自動附帶、XSS 是未轉義的輸出
  • 你會主動提到 least privilege 和 defense in depth,把 auth 決策連回實際場景(誰呼叫、多常、外洩損害多大)

Practice

Flashcards

Flashcards (1/10)

Cookie-based session 和 token-based auth 的核心差異?

Session:狀態存在 server(session store),cookie 只是查詢用的 ID → 可即時撤銷,但 scaling 需要 shared store。Token(JWT):狀態放在 token 本身,server 只驗簽名 → stateless、易水平擴展,但過期前無法撤銷。

Click card to flip

Quiz

Question 1/10

一個單一 server 的內部 admin dashboard,需要員工離職後立即失去存取權。最適合的 auth 方式?

Mark as Complete

3/5 — Okay