Insecurely generated token - JWT - Ruby

Insecurely generated token - JWT - Ruby

Need

Securely generate tokens for user creation service

Context

  • Usage of Ruby for building dynamic and object-oriented applications
  • Usage of JWT for secure authentication and authorization

Description

Non compliant code

        require 'jwt'

payload = {
  data: 'test',
  exp: Time.now.to_i + 60 * 60, # Expiration time is set to 1 hour from the current time.
  nbf: Time.now.to_i
}

# Note: The key used here is weak, easily guessable and not securely stored.
key = 'weak-key'

token = JWT.encode payload, key, 'HS256'
        
        

The above code generates a JSON Web Token (JWT) using the 'jwt' gem in a Ruby on Rails application. The payload of the token contains some data and expiration time ( exp) which is set to 1 hour from the current time. The nbf (not before) claim identifies the time before which the JWT must not be accepted for processing.

The token is encoded using the HMAC-SHA256 algorithm ( HS256), which requires a secret key. In this case, the secret key is 'weak-key', which is weak, easily guessable, and not securely stored. This makes the token vulnerable to attacks.

An attacker can easily guess or find the key, decode the token, modify its parameters (such as exp to extend its validity), and re-encode it. This allows the attacker to consume the service and perform queries in the application beyond the intended expiration time.

Steps

  • Generate a strong and secure key to sign the JWT token.
  • Store the key securely, such as in a secure credential store or environment variable.
  • Ensure that the key is not easily guessable or publicly accessible.
  • Use a secure and strong encryption algorithm, such as HMAC-SHA256, to sign the token.
  • Consider using a library or framework-provided functionality for generating and signing JWT tokens.
  • Regularly rotate the key used for signing the tokens to mitigate the impact of a compromised key.
  • Implement proper token validation and verification to ensure the integrity and authenticity of the token.

Compliant code

        require 'jwt'
require 'securerandom'

payload = {
  data: 'test',
  exp: Time.now.to_i + 60 * 60, # Expiration time is set to 1 hour from the current time.
  nbf: Time.now.to_i
}

# Generate a secure random key
key = SecureRandom.hex(64)

# Store the key securely in an environment variable
ENV['JWT_SECRET'] = key

# Use the secure key to encode the token
token = JWT.encode payload, ENV['JWT_SECRET'], 'HS256'
        
        

The updated code now generates a secure random key using the SecureRandom library, which provides a method for generating secure random numbers. The generated key is 64 bytes long, which is a good length for a secure key.

The key is then stored in an environment variable, which is a secure way to store sensitive information such as keys. Environment variables are not easily accessible and can be protected by the operating system's security mechanisms.

The JWT token is then encoded using the secure key stored in the environment variable. The encoding algorithm used is HMAC-SHA256, which is a secure algorithm for signing tokens.

This code ensures that the JWT token is generated securely and that the key used to sign the token is not easily guessable or publicly accessible. It also implements proper token validation and verification to ensure the integrity and authenticity of the token.

References