Hone logo
Hone
Problems

Implementing JWT Authentication in Python

This challenge focuses on building a foundational JWT (JSON Web Token) authentication system in Python. JWT is a widely used standard for securely transmitting information between parties as a JSON object. Implementing this will give you practical experience in creating secure token-based authentication, a critical skill for modern web applications.

Problem Description

You are tasked with creating a Python application that can:

  1. Generate JWTs: Given a user identifier and some arbitrary payload, create a signed JWT.
  2. Verify JWTs: Given a received JWT, validate its signature and expiration.
  3. Extract Claims: If a JWT is valid, extract the original claims (payload) from it.

This system should be robust enough to handle basic authentication scenarios.

Key Requirements:

  • JWT Generation:
    • The JWT should contain at least a user_id and an exp (expiration time) claim.
    • A secret key must be used to sign the JWT. This secret key should be configurable.
    • The JWT should be encoded using a common algorithm like HS256 (HMAC using SHA-256).
  • JWT Verification:
    • The verification process must check the JWT's signature against the provided secret key.
    • The verification process must also check the exp claim to ensure the token has not expired.
    • The algorithm used for verification must match the algorithm used for signing.
  • Claim Extraction:
    • If verification is successful, the function should return the decoded payload (claims) of the JWT.
  • Error Handling:
    • Appropriate exceptions should be raised for invalid tokens (e.g., expired, invalid signature).

Expected Behavior:

  • A function create_jwt(user_id: str, secret_key: str, algorithm: str = "HS256", expires_delta_seconds: int = 3600) -> str that takes user ID, secret key, algorithm, and expiration time in seconds, and returns a JWT string.
  • A function verify_jwt(token: str, secret_key: str, algorithm: str = "HS256") -> dict that takes a JWT string, secret key, and algorithm. It should return the decoded payload (as a dictionary) if valid, and raise an appropriate exception otherwise.

Edge Cases to Consider:

  • Tokens that have expired.
  • Tokens signed with an incorrect secret key.
  • Tokens with tampered payloads (which will result in an invalid signature).
  • Tokens generated with different algorithms.

Examples

Example 1: Token Generation and Successful Verification

# Assume current time is epoch_time_now
secret_key = "my_super_secret_key"
user_id = "user123"
expires_delta_seconds = 3600 # 1 hour

# Step 1: Generate the JWT
# The payload will be something like:
# {
#   "user_id": "user123",
#   "exp": epoch_time_now + 3600
# }
generated_token = create_jwt(user_id, secret_key, expires_delta_seconds=expires_delta_seconds)

# Step 2: Verify the JWT
# The verify_jwt function will check the signature and expiration.
decoded_payload = verify_jwt(generated_token, secret_key)

# Expected Output:
# The decoded_payload dictionary will contain the original claims.
# For instance:
# {
#   "user_id": "user123",
#   "exp": <some_future_timestamp>
# }

Example 2: Verification of an Expired Token

# Assume current time is epoch_time_now
secret_key = "my_super_secret_key"
user_id = "user456"

# Create a token that expired a long time ago
past_time = 1678886400 # An arbitrary past timestamp
expires_delta_seconds = -3600 # Make it expire in the past

# Step 1: Generate the JWT (will have an expired exp claim)
expired_token = create_jwt(user_id, secret_key, expires_delta_seconds=expires_delta_seconds)

# Step 2: Attempt to verify the expired JWT
# This should raise an exception (e.g., ExpiredSignatureError)
try:
    verify_jwt(expired_token, secret_key)
except Exception as e: # Replace with specific exception type if needed
    print(f"Verification failed: {e}")

# Expected Output:
# Verification failed: Token has expired

Example 3: Verification with an Invalid Secret Key

secret_key_correct = "correct_secret"
secret_key_wrong = "wrong_secret"
user_id = "user789"

# Step 1: Generate a JWT with the correct secret key
valid_token = create_jwt(user_id, secret_key_correct)

# Step 2: Attempt to verify the token with the wrong secret key
# This should raise an exception (e.g., InvalidSignatureError)
try:
    verify_jwt(valid_token, secret_key_wrong)
except Exception as e: # Replace with specific exception type if needed
    print(f"Verification failed: {e}")

# Expected Output:
# Verification failed: Invalid signature

Constraints

  • You must use the PyJWT library for JWT operations.
  • The secret_key will be a string of at least 16 characters.
  • The user_id will be a non-empty string.
  • The expires_delta_seconds will be an integer.
  • The algorithm will be one of the commonly supported JWT algorithms (e.g., "HS256").

Notes

  • You'll need to install the PyJWT library: pip install PyJWT.
  • Consider how to handle time. The datetime module in Python will be crucial for managing expiration times.
  • Think about the payload structure for your JWTs.
  • The PyJWT library provides specific exceptions for different types of verification failures (e.g., jwt.ExpiredSignatureError, jwt.InvalidSignatureError). It's good practice to catch and handle these specific exceptions.
Loading editor...
python