---
title: "Secure Catalyst APIs with API Key Authentication"
description: "Secure your Catalyst API using a shared secret."
canonicalUrl: "https://zuplo.com/use-cases/api-key-auth/perl/catalyst/secure-header"
framework: "Catalyst"
language: "Perl"
authStrategy: "shared secret header"
pageType: use-case
---

# Secure Catalyst APIs with API Key Authentication

Secure your Catalyst API using a shared secret.

## How Zuplo Handles It

Put Zuplo in front of your Catalyst backend to authenticate API keys and forward a shared secret header so your origin only accepts traffic from Zuplo.

## Catalyst Backend Code

```perl
package MyApp::Controller::Root;
use Moose;
use namespace::autoclean;
BEGIN { extends 'Catalyst::Controller' }

use Digest::SHA qw(sha256_hex);

__PACKAGE__->config(namespace => '');

sub validate_shared_secret :Private {
    my ($self, $c) = @_;

    my $secret = $c->request->header('x-shared-secret');
    my $expected_secret = $ENV{SHARED_SECRET};

    unless ($expected_secret) {
        $c->response->status(500);
        $c->response->body('Server configuration error');
        $c->detach;
    }

    unless ($secret) {
        $c->response->status(401);
        $c->response->body('No secret provided');
        $c->detach;
    }

    # Use a timing-safe comparison
    my $secret_hash = sha256_hex($secret);
    my $expected_hash = sha256_hex($expected_secret);

    unless ($secret_hash eq $expected_hash) {
        $c->response->status(401);
        $c->response->body('Invalid secret');
        $c->detach;
    }
}

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

    # Validate the shared secret
    $self->validate_shared_secret($c);

    # If the secret is valid:
    $c->response->status(200);
    $c->response->body('Access granted');
}

__PACKAGE__->meta->make_immutable;

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)
