---
title: "Add JWT Authentication to Your undefined API"
description: undefined
canonicalUrl: "https://zuplo.com/use-cases/api-key-auth/perl/catalyst/jwt-backend"
framework: undefined
language: undefined
authStrategy: "JWT with JWKS"
pageType: use-case
---

# Add JWT Authentication to Your undefined API



## How Zuplo Handles It

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

## undefined Backend Code

```perl
use strict;
use warnings;
use Catalyst qw/+CatalystX::InjectComponent/;
use JSON::JWK::Set;
use Crypt::JWT qw(decode_jwt);
use LWP::UserAgent;
use Try::Tiny;

# Define the issuer and JWKS URL
my $ISSUER = 'https://my-api-a32f34.zuplo.api/__zuplo/issuer';
my $JWKS_URI = "$ISSUER/.well-known/jwks.json";

# Fetch and cache the JWKS
my $ua = LWP::UserAgent->new;
my $jwks_response = $ua->get($JWKS_URI);
my $jwks_data = $jwks_response->decoded_content;
my $jwks = JSON::JWK::Set->new($jwks_data);

# Middleware to validate JWT
sub validate_jwt {
    my ($c) = @_;
    my $auth_header = $c->req->headers->authorization;

    unless ($auth_header && $auth_header =~ /^Bearer\s+(.+)/) {
        $c->response->status(401);
        $c->response->body('No token provided');
        return 0;
    }

    my $token = $1;

    try {
        my $decoded_token = decode_jwt(
            token        => $token,
            keyset       => $jwks,
            accepted_issuers => [$ISSUER],
            accepted_alg  => ['RS256'],
        );
        $c->stash->{user} = $decoded_token;
        return 1;
    }
    catch {
        $c->response->status(401);
        $c->response->body('Invalid token');
        return 0;
    };
}

# Example of route protected by the middleware
package MyApp::Controller::Protected;
use base 'Catalyst::Controller';

sub access_protected : Path('/protected') : Args(0) {
    my ($self, $c) = @_;

    return unless validate_jwt($c);

    $c->response->body('Access granted');
}

1;
```

## 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)
