payload = {
sub: user.id,
iss: 'https://auth.example.com',
aud: 'codesnips-api',
exp: 15.minutes.from_now.to_i,
iat: Time.now.to_i,
jti: SecureRandom.uuid,
}
token = JWT.encode(payload, OpenSSL::PKey::RSA.new(ENV.fetch('JWT_PRIVATE_KEY')), 'RS256')
decoded, = JWT.decode(
token,
OpenSSL::PKey::RSA.new(ENV.fetch('JWT_PUBLIC_KEY')),
true,
algorithm: 'RS256',
iss: 'https://auth.example.com',
verify_iss: true,
aud: 'codesnips-api',
verify_aud: true,
)
raise SecurityError, 'expired token' if decoded['exp'] < Time.now.to_i
JWTs are easy to misuse because libraries make them look simpler than they are. I pin the algorithm, validate issuer and audience, keep expirations short, and rotate signing keys deliberately. I also avoid putting sensitive business data into tokens just because it is convenient.