Back to Blog

Authentication in Modern Web Applications

Security patterns and best practices

August 8, 2024
8 min read

Authentication is the foundation of application security. After implementing various authentication systems, I've learned that the right approach depends on your specific requirements. Here's a practical guide to modern authentication patterns.

JWT: The Stateless Approach

JSON Web Tokens provide a stateless authentication mechanism. Here's a secure implementation:

import jwt
from datetime import datetime, timedelta
from fastapi import HTTPException, Depends
from fastapi.security import HTTPBearer

security = HTTPBearer()

def create_access_token(data: dict):
    to_encode = data.copy()
    expire = datetime.utcnow() + timedelta(minutes=15)
    to_encode.update({"exp": expire, "type": "access"})
    return jwt.encode(to_encode, SECRET_KEY, algorithm="HS256")

def create_refresh_token(data: dict):
    to_encode = data.copy()
    expire = datetime.utcnow() + timedelta(days=7)
    to_encode.update({"exp": expire, "type": "refresh"})
    return jwt.encode(to_encode, SECRET_KEY, algorithm="HS256")

Always use short-lived access tokens with longer-lived refresh tokens for better security.

Password Security Best Practices

Hashing with Salt

import bcrypt

def hash_password(password: str) -> str:
    salt = bcrypt.gensalt()
    return bcrypt.hashpw(password.encode('utf-8'), salt).decode('utf-8')

def verify_password(password: str, hashed: str) -> bool:
    return bcrypt.checkpw(
        password.encode('utf-8'), 
        hashed.encode('utf-8')
    )

Rate Limiting

Implement rate limiting on authentication endpoints to prevent brute force attacks. Use tools like Redis for distributed rate limiting.

OAuth 2.0 Integration

OAuth provides secure third-party authentication. Here's a Google OAuth example:

from authlib.integrations.fastapi_oauth2 import OAuth2Token
from authlib.integrations.httpx_oauth2 import OAuth2Client

oauth2_client = OAuth2Client(
    client_id=GOOGLE_CLIENT_ID,
    client_secret=GOOGLE_CLIENT_SECRET,
    authorize_url="https://accounts.google.com/o/oauth2/auth",
    token_url="https://oauth2.googleapis.com/token",
)

@app.get("/auth/google")
async def google_auth():
    redirect_uri = "http://localhost:8000/auth/callback"
    return await oauth2_client.authorize_redirect(redirect_uri)

@app.get("/auth/callback")
async def google_callback(code: str):
    token = await oauth2_client.fetch_token(code)
    user_info = await get_google_user_info(token['access_token'])
    # Create or update user in database
    return {"user": user_info}

Security Checklist

  • Always use HTTPS in production
  • Implement proper CORS policies
  • Use secure, httpOnly cookies for sensitive data
  • Implement account lockout after failed attempts
  • Add two-factor authentication for sensitive operations
  • Log authentication events for monitoring
  • Regularly rotate secrets and keys

Final Thoughts

Authentication is not just about verifying identity - it's about building trust with your users. The patterns I've shared here have worked well in production applications, but always consider your specific security requirements and compliance needs. Security is an ongoing process, not a one-time implementation.