Hone logo
Hone
Problems

Secure Your API: JWT Authentication in Python

JWT (JSON Web Token) authentication is a standard method for securing APIs. This challenge asks you to implement a basic JWT authentication system in Python, allowing you to generate, verify, and decode JWTs. This is crucial for building secure and scalable applications where you need to authenticate users and authorize access to resources.

Problem Description

You are tasked with creating a Python module that handles JWT authentication. The module should include functions for:

  1. Generating a JWT: This function should take a payload (a dictionary containing user information, e.g., user ID, username) and a secret key as input. It should generate a signed JWT using the provided payload and secret key. The JWT should be encoded as a string.
  2. Verifying a JWT: This function should take a JWT string and the secret key as input. It should verify the signature of the JWT and return the decoded payload if the JWT is valid. If the JWT is invalid (e.g., signature mismatch, expired), it should raise an exception.
  3. Decoding a JWT: This function should take a JWT string and the secret key as input. It should decode the JWT without verifying the signature. This is useful for scenarios where you only need to access the payload information without validating the token's authenticity. If the JWT is invalid, it should raise an exception.

Key Requirements:

  • Use the PyJWT library for JWT generation and verification. You'll need to install it: pip install PyJWT
  • The secret key should be used for both signing and verifying JWTs.
  • The payload should be a Python dictionary.
  • The JWT should be encoded using UTF-8.
  • The expiration time (exp) claim should be included in the payload when generating a JWT. Set the expiration time to 3600 seconds (1 hour) from the current time.

Expected Behavior:

  • The generate_jwt function should return a valid JWT string.
  • The verify_jwt function should return the decoded payload if the JWT is valid.
  • The decode_jwt function should return the decoded payload if the JWT is valid.
  • All three functions should raise an exception (e.g., InvalidTokenError) if the JWT is invalid or cannot be processed.

Edge Cases to Consider:

  • Invalid JWT format (e.g., missing header, payload, or signature).
  • Signature mismatch (JWT has been tampered with).
  • Expired JWT (the exp claim has passed).
  • Invalid secret key.
  • Empty payload.

Examples

Example 1:

Input: payload = {"user_id": 123, "username": "testuser"}, secret_key = "my_secret_key"
Output: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsInVzZXJuYW1lIjoicGVzdHVzZXIiLCJleHAiOjE3MDc0ODU0MDB9.some_signature" (The signature part will vary)
Explanation: A JWT is generated with the given payload and secret key, including an expiration time.

Example 2:

Input: jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsInVzZXJuYW1lIjoicGVzdHVzZXIiLCJleHAiOjE3MDc0ODU0MDB9.some_signature", secret_key = "my_secret_key"
Output: {'user_id': 123, 'username': 'testuser', 'exp': 1707485400}
Explanation: The JWT is verified against the secret key, and the decoded payload is returned.

Example 3: (Expired JWT)

Input: jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsInVzZXJuYW1lIjoicGVzdHVzZXIiLCJleHAiOjE2OTgwNzA0MDB9.some_signature", secret_key = "my_secret_key" (Assuming the current time is later than the expiration time in the JWT)
Output: Raises InvalidTokenError (or a similar exception indicating an invalid token)
Explanation: The JWT has expired, so verification fails and an exception is raised.

Constraints

  • The secret key must be a string of at least 16 characters.
  • The payload must be a dictionary.
  • The expiration time (exp) claim must be a Unix timestamp (seconds since epoch).
  • The JWT library (PyJWT) must be used.
  • The code should be well-documented and easy to understand.

Notes

  • Consider using the datetime module to calculate the expiration time.
  • Handle potential exceptions gracefully and provide informative error messages.
  • Focus on the core functionality of generating, verifying, and decoding JWTs. You don't need to implement user registration or authentication flows.
  • The signature of the generated JWT will vary depending on the secret key and the order of keys in the payload dictionary. Don't hardcode the signature in your tests.
  • Think about how to structure your code for reusability and maintainability. Consider creating a class to encapsulate the JWT authentication logic.
Loading editor...
python