Get a Pentest and security assessment of your IT network.

Cyber Security

Stateless App Authentication: Avoid DB Hits

TL;DR

Use JWTs (JSON Web Tokens) to authenticate users after their initial login. Store the token securely on the client-side and include it in every request. Verify the token on the server instead of querying the database for each request.

How to Avoid Database Authentication Hits

  1. Initial Login: When a user logs in (username/password), authenticate them against your database as usual.
    • If successful, create a JWT.
    • The JWT contains information about the user (e.g., user ID, roles) and an expiry time.
    • Sign the JWT with a secret key. Keep this key extremely secure!
  2. JWT Creation Example (Python using PyJWT):
    import jwt
    import datetime
    
    secret_key = 'your-super-secret-key'
    payload = {
        'user_id': user.id,
        'roles': user.roles,
        'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=30) # Token expires in 30 minutes
    }
    token = jwt.encode(payload, secret_key, algorithm='HS256')
    print(token)
    
  3. Store the JWT on the Client: Send the generated JWT back to the client (e.g., in an HTTP-only cookie or local storage). HTTP-only cookies are generally more secure than local storage.
    • Avoid storing sensitive information directly in the token; only include necessary data for authorization.
  4. Include JWT in Subsequent Requests: The client includes the JWT in the Authorization header of every subsequent request (typically as a Bearer token).
    Authorization: Bearer <your_jwt_token>
    
  5. Server-Side Verification: On the server, intercept the JWT from the Authorization header.
    • Verify the token’s signature using your secret key.
    • If the signature is valid and the token hasn’t expired, extract the user information from the payload.
    • Grant access based on the extracted user data.
  6. JWT Verification Example (Python using PyJWT):
    import jwt
    
    secret_key = 'your-super-secret-key'
    token = request.headers.get('Authorization').split()[1] # Extract token from header
    try:
        payload = jwt.decode(token, secret_key, algorithms=['HS256'])
        user_id = payload['user_id']
        # Access user data without hitting the database
    except jwt.ExpiredSignatureError:
        return 'Token has expired', 401
    except jwt.InvalidTokenError:
        return 'Invalid token', 401
    
  7. Refresh Tokens (Optional): Implement refresh tokens to allow users to stay logged in for longer periods without re-entering their credentials.
    • When the JWT expires, use a long-lived refresh token to request a new JWT.
    • Store refresh tokens securely and rotate them regularly.

Important Considerations

  • Secret Key Security: Protect your secret key at all costs! Do not hardcode it into your application; use environment variables or a secure configuration management system.
  • Token Expiry: Set appropriate token expiry times to balance security and user experience. Shorter expiry times are more secure but require more frequent refreshing.
  • Statelessness: Ensure your server doesn’t store any session information; all necessary data should be contained within the JWT.
  • Revocation: Consider implementing a token revocation mechanism if you need to invalidate tokens before their expiry time (e.g., when a user logs out). This can be achieved with a blacklist or by using short-lived tokens and frequent refreshing.
Related posts
Cyber Security

Zip Codes & PII: Are They Personal Data?

Cyber Security

Zero-Day Vulnerabilities: User Defence Guide

Cyber Security

Zero Knowledge Voting with Trusted Server

Cyber Security

ZeroNet: 51% Attack Risks & Mitigation