---
title: "Add JWT Authentication to Your Cuba API"
description: "Secure your Cuba API using JWT authentication with JWKS."
canonicalUrl: "https://zuplo.com/use-cases/api-key-auth/ruby/cuba/jwt-backend"
framework: "Cuba"
language: "Ruby"
authStrategy: "JWT with JWKS"
pageType: use-case
---

# Add JWT Authentication to Your Cuba API

Secure your Cuba API using JWT authentication with JWKS.

## How Zuplo Handles It

Let Zuplo issue short-lived JWTs signed with a JWKS your Cuba backend can verify — no long-lived API keys touch your origin.

## Cuba Backend Code

```ruby
require 'cuba'
require 'jwt'
require 'net/http'
require 'json'

ISSUER = 'https://my-api-a32f34.zuplo.api/__zuplo/issuer'
JWKS_URI = "#{ISSUER}/.well-known/jwks.json"

# JWKS cache
$jwks_cache = nil
$jwks_cache_time = nil

def fetch_jwks
  if $jwks_cache.nil? || Time.now - $jwks_cache_time > 600
    uri = URI(JWKS_URI)
    response = Net::HTTP.get(uri)
    $jwks_cache = JSON.parse(response)
    $jwks_cache_time = Time.now
  end
  $jwks_cache
end

def get_signing_key(kid)
  jwks = fetch_jwks
  key = jwks['keys'].find { |k| k['kid'] == kid }
  return nil unless key
  JWT::JWK.import(key)
end

def authenticate_jwt!(req, res)
  auth_header = req.env['HTTP_AUTHORIZATION']
  token = auth_header&.gsub('Bearer ', '')

  unless token
    res.status = 401
    res.write({ error: 'No token provided' }.to_json)
    return nil
  end

  begin
    headers = JWT.decode(token, nil, false).last
    kid = headers['kid']
    jwk = get_signing_key(kid)

    decoded = JWT.decode(token, jwk.public_key, true, {
      iss: ISSUER,
      verify_iss: true,
      algorithms: ['RS256']
    })

    decoded.first
  rescue JWT::DecodeError, JWT::VerificationError => e
    res.status = 401
    res.write({ error: 'Invalid token', details: e.message }.to_json)
    nil
  end
end

Cuba.define do
  on get do
    on 'protected' do
      user = authenticate_jwt!(req, res)
      if user
        res.write({ message: 'Access granted', user: user }.to_json)
      end
    end
  end
end
```

## Example Request

```bash
curl -X GET \
  'https://your-api.zuplo.dev/your-route' \
  -H 'Authorization: Bearer YOUR_API_KEY'
```

## Learn More

- [API Key Authentication on Zuplo](https://zuplo.com/docs/policies/api-key-auth-inbound)
- [JWT Authentication on Zuplo](https://zuplo.com/docs/policies/open-id-jwt-auth-inbound)
- [All use cases](https://zuplo.com/use-cases)
