API Security Patterns

Preview — 3 of 10 questions

A healthcare SaaS stores patient medical records in a PostgreSQL database on AWS. The records are encrypted at rest with AES-256. Is this sufficient to protect against all data leaks?

javascript
Encryption at rest protects against:
   Someone stealing the physical disk
   Improper disposal of decommissioned servers
   Unauthorized access to backup files

Encryption at rest does NOT protect against:
   Data intercepted in transit (network sniffing)
   SQL injection (attacker queries decrypted data through the app)
   Compromised application server (data decrypted in memory)
   Unauthorized DB access (DB decrypts data for any authenticated connection)

Defense-in-depth for healthcare (HIPAA-compliant example):
  1. Encryption at rest: AES-256 (disk-level or column-level)
  2. Encryption in transit: TLS 1.3 for all connections (app→DB, client→app)
  3. Column-level encryption: PII fields encrypted even inside the DB
     (only decryptable by the app, not by a DBA with DB access)
  4. Access control: least privilege  app DB user can only SELECT/INSERT specific tables
  5. Audit logging: all access to sensitive records logged
  6. Network isolation: DB only accessible from within VPC, not public internet
AYes — AES-256 encryption at rest is the strongest standard and protects against all threats.
BNo — encryption at rest protects against physical disk theft or improper hardware disposal, but data is decrypted when the database processes it. Unencrypted data in transit (between app and DB) or in memory is still vulnerable.
CNo — AES-256 is outdated; ChaCha20 should be used instead.
DYes — AWS handles all encryption automatically and no additional measures are needed.

A third-party app wants to read a user's Google Calendar on their behalf. Which OAuth 2.0 flow is appropriate, and why is the implicit flow (which sends tokens directly in the URL fragment) now considered insecure?

javascript
OAuth 2.0 flows comparison:

Authorization Code Flow ( recommended):
  User  App  Google: "I want to access Calendar"
  Google  User: "Allow App to access Calendar?" [consent screen]
  User approves  Google  App: authorization CODE (short-lived, ~10s)
  App  Google: exchanges CODE + client_secret for access_token
  
  Code in URL: safe (expires in seconds, single-use, not a token itself)
  Token exchange: server-to-server (never visible in browser)

Implicit Flow ( deprecated):
  Google  Browser: access_token in URL fragment (#access_token=xxx)
  
  Problems:
  - Token visible in browser history, server logs, referrer headers
  - If user is on shared computer  token exposed
  - No way to authenticate the client app (no client_secret)
  - Token can be stolen from URL before app reads it

PKCE (Proof Key for Code Exchange):
  For mobile/SPA apps that can't keep a client_secret:
  App generates: code_verifier (random) → hashes it → code_challenge
  Sends code_challenge with auth request
  Server verifies: when exchanging code, app must prove it knows code_verifier
  → Even if code is intercepted, attacker can't exchange it without code_verifier
AUse the client credentials flow — it's the most secure because there's no user involvement.
BUse the resource owner password credentials flow, which sends the username and password directly to the third-party app.
CUse the authorization code flow with PKCE. The implicit flow is insecure because access tokens appear in the browser URL (and thus in logs, referrer headers, and history), and there's no way to verify the app's identity.
DUse the implicit flow — it's faster because it returns tokens immediately without an extra code exchange.

A Node.js API uses JWTs for authentication. A developer notices the token header specifies "alg": "HS256". An attacker attempts to change the algorithm to "alg": "none". What must the server do to prevent this attack?

javascript
The "alg: none" vulnerability:
  JWT structure: header.payload.signature
  
  Original valid token:
  header:    {"alg": "HS256", "typ": "JWT"}
  payload:   {"userId": "user_123", "role": "user"}
  signature: HMAC-SHA256(header + "." + payload, secret)
  
  Attacker modifies:
  header:    {"alg": "none", "typ": "JWT"}
  payload:   {"userId": "user_123", "role": "ADMIN"}   escalated!
  signature: (empty)
  
  Vulnerable server:
    Reads "alg: none" from header
    Skips signature verification (no algo = no signature needed)
    Accepts the forged admin token! 

Secure implementation (Node.js example):
  // ❌ Vulnerable
  jwt.verify(token, secret); // uses algorithm from token header
  
  // ✅ Secure
  jwt.verify(token, secret, { algorithms: ['HS256'] });
  // Explicitly whitelist; "none" or "RS256" → rejected
AThe server should accept "alg": "none" for non-sensitive endpoints to improve performance.
BChanging the algorithm in the header invalidates the signature automatically, making this attack impossible.
CThe server must explicitly whitelist accepted algorithms and reject tokens with "alg": "none" or unexpected algorithms — never trust the algorithm declared in the token header.
DJWT libraries automatically reject "alg": "none" since it was patched in 2015.

Sign up free to play

Answer all 10 questions (7 more), see explanations for every answer, and track your score.