Authentication is the foundation of security. Here's how we approach it at Google.
Session-Based Authentication
Server creates a session, stores it in memory/database, sends a session ID cookie to the client.
// Server sets cookie
Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=Strict; Path=/
// Every subsequent request includes the cookie automatically
Cookie: session_id=abc123Pros: Server can revoke sessions instantly. HttpOnly cookies prevent XSS theft.
Cons: Server must store session state. Doesn't scale well across multiple servers without shared storage.
JWT (JSON Web Tokens)
// JWT structure: header.payload.signature
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiMTIzIiwiZXhwIjoxNjk5MDAwMDAwfQ.signature
// Payload (claims)
{
"user_id": "123",
"role": "admin",
"exp": 1699000000, // expiration
"iat": 1698900000 // issued at
}Pros: Stateless, works across services, contains user info.
Cons: Can't be revoked until expiration. Larger than session IDs. Must handle refresh tokens.
The Refresh Token Pattern
// Short-lived access token (15 min) + long-lived refresh token (7 days)
// Access token: sent in Authorization header
// Refresh token: stored in HttpOnly cookie
async function refreshAccessToken() {
const res = await fetch("/auth/refresh", { credentials: "include" });
const { accessToken } = await res.json();
return accessToken;
}OAuth 2.0 Flow
- User clicks "Login with Google"
- Redirect to Google's authorization server
- User grants permission
- Google redirects back with authorization code
- Your server exchanges code for access token
- Server creates session or JWT for your app
Security Best Practices
- Store JWTs in HttpOnly cookies, not localStorage
- Use short expiration for access tokens (15 min)
- Implement CSRF protection with SameSite cookies
- Always validate tokens on the server, never trust the client
- Use PKCE for public clients (SPAs, mobile apps)