Try it yourself with our free Jwt Decoder tool — runs entirely in your browser, no signup needed.

How to Verify JWT token signatures in Ruby

How to verify JWT token signatures in Ruby

JSON Web Tokens (JWTs) are a widely-used standard for securely transmitting information between parties. Verifying the signature of a JWT token is crucial to ensure its authenticity and integrity. In this article, we will explore how to verify JWT token signatures in Ruby, covering a quick example, a step-by-step breakdown, handling edge cases, common mistakes, performance tips, and frequently asked questions.

Quick Example

Here is a minimal example of verifying a JWT token signature using the jwt gem:

require 'jwt'

def verify_jwt_token(token, secret_key)
  begin
    decoded_token = JWT.decode(token, secret_key, ['HS256'])
    return decoded_token
  rescue JWT::VerificationError
    return nil
  end
end

token = "your_jwt_token_here"
secret_key = "your_secret_key_here"
decoded_token = verify_jwt_token(token, secret_key)
puts decoded_token

This example uses the jwt gem, which can be installed via gem install jwt.

Step-by-Step Breakdown

Let's walk through the code:

  1. require 'jwt': We require the jwt gem, which provides the necessary functionality for working with JWTs.
  2. def verify_jwt_token(token, secret_key): We define a method verify_jwt_token that takes two arguments: token (the JWT token to verify) and secret_key (the secret key used to sign the token).
  3. begin: We start a begin block to catch any exceptions that may occur during the verification process.
  4. decoded_token = JWT.decode(token, secret_key, ['HS256']): We use the JWT.decode method to decode the token using the provided secret key and the HS256 algorithm (a widely-used algorithm for JWTs). The decode method returns the decoded token payload if the signature is valid.
  5. return decoded_token: If the signature is valid, we return the decoded token payload.
  6. rescue JWT::VerificationError: We catch the JWT::VerificationError exception, which is raised if the signature is invalid.
  7. return nil: If the signature is invalid, we return nil to indicate failure.

Handling Edge Cases

Here are some common edge cases to consider:

Empty/null input

token = nil
secret_key = "your_secret_key_here"
decoded_token = verify_jwt_token(token, secret_key)
puts decoded_token # => nil

In this case, the verify_jwt_token method will return nil because the input token is nil.

Invalid input

token = " invalid_token "
secret_key = "your_secret_key_here"
decoded_token = verify_jwt_token(token, secret_key)
puts decoded_token # => nil

In this case, the verify_jwt_token method will return nil because the input token is invalid.

Large input

token = "a" * 10000
secret_key = "your_secret_key_here"
decoded_token = verify_jwt_token(token, secret_key)
puts decoded_token # => nil

In this case, the verify_jwt_token method will return nil because the input token is too large.

Unicode/special characters

token = "your_jwt_token_here"
secret_key = "your_secret_key_here"
decoded_token = verify_jwt_token(token, secret_key)
puts decoded_token # => decoded token payload

In this case, the verify_jwt_token method will return the decoded token payload because the input token contains Unicode/special characters.

Common Mistakes

Here are three common mistakes developers make when verifying JWT token signatures in Ruby:

Mistake 1: Not handling exceptions

def verify_jwt_token(token, secret_key)
  decoded_token = JWT.decode(token, secret_key, ['HS256'])
  return decoded_token
end

Corrected code:

def verify_jwt_token(token, secret_key)
  begin
    decoded_token = JWT.decode(token, secret_key, ['HS256'])
    return decoded_token
  rescue JWT::VerificationError
    return nil
  end
end

Mistake 2: Not validating the secret key

def verify_jwt_token(token, secret_key)
  decoded_token = JWT.decode(token, secret_key, ['HS256'])
  return decoded_token
end

Corrected code:

def verify_jwt_token(token, secret_key)
  if secret_key.blank?
    raise ArgumentError, "Secret key cannot be blank"
  end
  begin
    decoded_token = JWT.decode(token, secret_key, ['HS256'])
    return decoded_token
  rescue JWT::VerificationError
    return nil
  end
end

Mistake 3: Not checking the token payload

def verify_jwt_token(token, secret_key)
  decoded_token = JWT.decode(token, secret_key, ['HS256'])
  return decoded_token
end

Corrected code:

def verify_jwt_token(token, secret_key)
  begin
    decoded_token = JWT.decode(token, secret_key, ['HS256'])
    if decoded_token['exp'] < Time.now.to_i
      raise ArgumentError, "Token has expired"
    end
    return decoded_token
  rescue JWT::VerificationError
    return nil
  end
end

Performance Tips

Here are two performance tips for verifying JWT token signatures in Ruby:

Tip 1: Use a caching layer

require 'redis'

def verify_jwt_token(token, secret_key)
  cache = Redis.new
  cached_token = cache.get(token)
  if cached_token
    return cached_token
  end
  begin
    decoded_token = JWT.decode(token, secret_key, ['HS256'])
    cache.set(token, decoded_token)
    return decoded_token
  rescue JWT::VerificationError
    return nil
  end
end

Tip 2: Use a faster algorithm

require 'jwt'

def verify_jwt_token(token, secret_key)
  begin
    decoded_token = JWT.decode(token, secret_key, ['HS512'])
    return decoded_token
  rescue JWT::VerificationError
    return nil
  end
end

FAQ

Q: What is the difference between HS256 and HS512?

A: HS256 and HS512 are two different algorithms used for signing JWTs. HS256 is a faster algorithm, while HS512 is more secure.

Q: How do I generate a secret key?

A: You can generate a secret key using a random string generator or a library like SecureRandom.

Q: Can I use a different algorithm for signing JWTs?

A: Yes, you can use different algorithms like RS256 or ES256, but you need to make sure the algorithm is supported by the jwt gem.

Q: How do I handle token expiration?

A: You can check the exp claim in the token payload to determine if the token has expired.

Q: Can I use JWTs for authentication?

A: Yes, JWTs can be used for authentication, but you need to make sure to validate the token payload and handle token expiration.

AI agent tools available. The CodeTidy MCP Server gives Claude, Cursor, and other AI agents access to 60+ developer tools. One command: npx @codetidy/mcp