Skip to main content

Security Basics

TL;DR (30-second summary)

Authentication: Verify identity (who you are). Authorization: Check permissions (what you can do). OAuth: Let users login with Google/Facebook. JWT: Stateless tokens. Encryption: HTTPS (in transit), AES (at rest).

Golden rule: Never trust user input. Always validate, sanitize, and authenticate.

Why This Matters

In interviews: Security is non-negotiable. Shows you think about real-world threats and compliance (GDPR, PCI-DSS).

At work: Security breaches cost millions and destroy trust.

Core Concepts

1. Authentication vs Authorization

ConceptQuestionExample
AuthenticationWho are you?Login with username/password
AuthorizationWhat can you do?Admin can delete, user can only read

2. Authentication Methods

Session-Based (Traditional)

Pros:

  • ✅ Can revoke immediately (delete session)
  • ✅ Secure (session ID is meaningless)

Cons:

  • ❌ Stateful (requires session store)
  • ❌ Doesn't scale horizontally (sticky sessions or shared session store)

Token-Based (JWT)

JWT Structure:

Header.Payload.Signature

eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiMTIzIn0.abc123xyz

Decoded:

// Header
{"alg": "HS256", "typ": "JWT"}

// Payload
{"user_id": "123", "role": "admin", "exp": 1642345600}

// Signature (verifies token hasn't been tampered with)
HMACSHA256(base64(header) + "." + base64(payload), secret)

Pros:

  • ✅ Stateless (no session store needed)
  • ✅ Scales horizontally
  • ✅ Can include user data in payload (avoid DB lookup)

Cons:

  • ❌ Can't revoke until expiry (use short TTL: 15-60 min)
  • ❌ Payload is visible (base64, not encrypted)
  • ❌ Token size larger than session ID (impacts bandwidth)
Red Flag

Never store sensitive data in JWT (e.g., passwords, credit cards). Payload is BASE64-encoded, not encrypted!

Best practice: Use short-lived JWT (15 min) + refresh token (stored securely).

3. OAuth 2.0

Purpose: Let users login with 3rd-party providers (Google, Facebook, GitHub) without sharing passwords.

OAuth Roles:

  • Resource Owner: User
  • Client: Your app
  • Authorization Server: Google/Facebook
  • Resource Server: Google's API (user profile)

OAuth Scopes (permissions):

scope=read:user,write:repo

Use cases:

  • "Login with Google" (authentication)
  • Grant app access to Google Drive (authorization)

4. Authorization Patterns

Role-Based Access Control (RBAC)

{
"user_id": "123",
"roles": ["admin", "editor"]
}

Check:

if "admin" in user.roles:
allow_delete()

Pros: Simple, easy to manage
Cons: Coarse-grained (can't express complex permissions)

Permission-Based (Fine-Grained)

{
"user_id": "123",
"permissions": [
"users:read",
"users:write",
"posts:delete"
]
}

Check:

if "posts:delete" in user.permissions:
delete_post()

Pros: Flexible, fine-grained
Cons: More complex to manage

Attribute-Based Access Control (ABAC)

# Rule: User can edit post if they are the author
if user.id == post.author_id:
allow_edit()

# Rule: User can view document if department matches
if user.department == document.department:
allow_view()

Pros: Very flexible, context-aware
Cons: Complex rules, harder to debug

5. Common Vulnerabilities

SQL Injection

Attack:

# Vulnerable code
query = f"SELECT * FROM users WHERE email = '{email}'"
# Attacker input: email = "' OR '1'='1"
# Resulting query: SELECT * FROM users WHERE email = '' OR '1'='1'
# Returns all users!

Fix (Parameterized queries):

query = "SELECT * FROM users WHERE email = ?"
db.execute(query, [email]) # Safe - input is escaped

Cross-Site Scripting (XSS)

Attack:

<!-- User input: <script>alert('XSS')</script> -->
<div>Comment: <script>alert('XSS')</script></div>
<!-- Script executes in victim's browser -->

Fix (Output encoding):

<div>Comment: &lt;script&gt;alert('XSS')&lt;/script&gt;</div>
<!-- Displays as text, doesn't execute -->

Cross-Site Request Forgery (CSRF)

Attack:

<!-- Malicious site -->
<img src="https://bank.com/transfer?to=attacker&amount=1000">
<!-- If user is logged into bank.com, request succeeds -->

Fix (CSRF tokens):

<form action="/transfer" method="POST">
<input type="hidden" name="csrf_token" value="abc123...">
<input name="to" value="...">
<button>Transfer</button>
</form>

Server validates token before processing request.

6. Encryption

Data in Transit (HTTPS/TLS)

Purpose: Encrypt data traveling over the network.

Without HTTPS: Attacker can see passwords, credit cards (man-in-the-middle attack).

Always use HTTPS for production APIs.

Data at Rest

Purpose: Encrypt data stored in database or disk.

Algorithms:

  • AES-256: Symmetric encryption (same key for encrypt/decrypt)
  • RSA-2048: Asymmetric encryption (public/private key pair)

Example (Database encryption):

# Encrypt before storing
encrypted_ssn = aes_encrypt(ssn, key)
db.insert(user_id, encrypted_ssn)

# Decrypt when reading
encrypted_ssn = db.get(user_id)
ssn = aes_decrypt(encrypted_ssn, key)

Use cases:

  • Credit card numbers
  • Social security numbers
  • Medical records (HIPAA compliance)

Key management:

  • Never hardcode keys in code
  • Use secrets management (AWS Secrets Manager, HashiCorp Vault)
  • Rotate keys periodically

Hashing (One-Way)

Purpose: Store passwords securely (can't be reversed).

Never store plain-text passwords:

# WRONG
db.insert(user_id, password) # ❌ Plain-text

# RIGHT
hashed = bcrypt.hash(password) # ✅ Hashed
db.insert(user_id, hashed)

Verify login:

stored_hash = db.get(user_id)
if bcrypt.verify(password, stored_hash):
login_success()

Algorithms:

  • bcrypt: Recommended for passwords (slow, with salt)
  • Argon2: Modern, resistant to GPU attacks
  • SHA-256: Fast, but NOT for passwords (too fast = easy to brute-force)

Salt (random data added to password before hashing):

password: "hello123"
salt: "a1b2c3d4"
hash(password + salt) → "xyz789..."

Prevents rainbow table attacks (pre-computed hashes)

7. API Security Best Practices

PracticeWhy
HTTPS everywhereEncrypt data in transit
Rate limitingPrevent brute-force, DDoS
Input validationPrevent SQL injection, XSS
Parameterized queriesPrevent SQL injection
Output encodingPrevent XSS
CSRF tokensPrevent CSRF attacks
JWT with short expiryLimit damage if token stolen (15-60 min)
Password hashingbcrypt/Argon2 with salt
Secrets managementNever hardcode API keys/passwords
CORS headersRestrict which domains can call API
Security headersX-Frame-Options, Content-Security-Policy

Security headers:

Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'

Common Interview Questions

Q1: "Explain JWT and its trade-offs."

Answer:

  • What: JSON Web Token - self-contained, stateless authentication
  • Structure: Header.Payload.Signature (base64 encoded)
  • Pros: Stateless (scales horizontally), no session store
  • Cons: Can't revoke until expiry, payload visible (not encrypted)
  • Best practice: Short TTL (15 min) + refresh token

Q2: "How do you prevent SQL injection?"

Answer:

  • Use parameterized queries (prepared statements)
  • Never concatenate user input into SQL string
  • Example:
    # Vulnerable: query = f"SELECT * FROM users WHERE id = {user_id}"
    # Safe: db.execute("SELECT * FROM users WHERE id = ?", [user_id])

Q3: "Session-based vs token-based authentication?"

Answer:

AspectSession-BasedToken-Based (JWT)
StateStateful (session store)Stateless
ScalabilityHarder (sticky sessions)Easier (any server can validate)
RevocationImmediate (delete session)Wait for expiry
Use caseMonoliths, server-rendered appsMicroservices, SPAs, mobile

Q4: "How do you securely store passwords?"

Answer:

  1. Never plain-text - hash with bcrypt/Argon2
  2. Salt - add random data to prevent rainbow tables
  3. Slow algorithm - bcrypt is intentionally slow (resist brute-force)
  4. Example:
    hashed = bcrypt.hash(password, salt_rounds=12)
    db.insert(user_id, hashed)

Trade-offs

DecisionOption AOption BConsider
AuthSession-based (stateful)JWT (stateless)Scalability vs revocation
Passwordbcrypt (proven)Argon2 (modern)Compatibility vs security
EncryptionAES-256 (symmetric)RSA (asymmetric)Speed vs key distribution
OAuthOwn auth system3rd-party (Google)Control vs convenience

Real-World Examples

Auth0 (Authentication as a Service)

  • Handles: Login, OAuth, MFA, JWT
  • Use case: Offload auth complexity
  • Result: 2 billion logins/month for 8000+ companies

Stripe (Payment Security)

  • PCI-DSS Level 1 compliant (highest security standard)
  • Encryption: TLS 1.2+, AES-256 at rest
  • Tokenization: Never store raw card numbers
  • Result: Process $1 trillion/year securely

GitHub (OAuth Provider)

  • OAuth scopes: repo, user, admin:org
  • Personal access tokens: Fine-grained permissions
  • 2FA: Required for sensitive operations

Quick Reference Card

Authentication:

  • Session: Stateful, use for monoliths
  • JWT: Stateless, use for microservices/mobile
  • OAuth: 3rd-party login (Google, Facebook)

Authorization:

  • RBAC: Role-based (simple)
  • ABAC: Attribute-based (flexible)

Encryption:

  • In transit: HTTPS/TLS (always)
  • At rest: AES-256 (sensitive data)
  • Passwords: bcrypt/Argon2 (one-way hash)

Common vulnerabilities:

  • SQL Injection: Use parameterized queries
  • XSS: Encode output
  • CSRF: Use CSRF tokens

Security headers:

Strict-Transport-Security: max-age=31536000
X-Frame-Options: DENY
Content-Security-Policy: default-src 'self'

Further Reading


Next: Monitoring & Observability - Logging, metrics, tracing, alerting.