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

# Add JWT Authentication to Your Sinatra API

Secure your Sinatra API using JWT authentication with JWKS.

## How Zuplo Handles It

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

## Sinatra Backend Code

```ruby
require 'sinatra'
require 'jwt'
require 'net/http'
require 'uri'
require 'json'

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

def fetch_jwks
  uri = URI(JWKS_URI)
  response = Net::HTTP.get(uri)
  JSON.parse(response)
end

def get_signing_key(kid)
  jwks = fetch_jwks
  keys = jwks['keys'].select { |key| key['kid'] == kid }
  return nil if keys.empty?

  key = keys.first
  JWT::JWK.import(key)
end

def authorize_request!(request)
  auth_header = request.env['HTTP_AUTHORIZATION']
  token = auth_header&.gsub('Bearer ', '')

  halt 401, { error: 'No token provided' }.to_json unless token

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

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

    request.env[:user] = decoded_token.first
  rescue JWT::DecodeError, JWT::VerificationError => e
    halt 401, { error: 'Invalid token', details: e.message }.to_json
  end
end

before '/protected' do
  authorize_request!(request)
end

get '/protected' do
  user = request.env[:user]
  { message: 'Access granted', user: user }.to_json
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)
