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

# Secure Mojolicious APIs with API Key Authentication

Secure your Mojolicious API using a shared secret.

## How Zuplo Handles It

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

## Mojolicious Backend Code

```perl
use Mojolicious::Lite;
use Crypt::Mac::HMAC qw(hmac_b64u);

helper validate_shared_secret => sub {
  my $c = shift;

  my $secret = $c->req->headers->header('X-Shared-Secret');
  my $expected_secret = $ENV{SHARED_SECRET};

  return $c->render(json => {error => 'Server configuration error'}, status => 500)
    unless defined $expected_secret;

  return $c->render(json => {error => 'No secret provided'}, status => 401)
    unless defined $secret;

  # Use constant time comparison to prevent timing attacks
  if (length($secret) ne length($expected_secret) ||
      hmac_b64u($secret, '') ne hmac_b64u($expected_secret, '')) {
    return $c->render(json => {error => 'Invalid secret'}, status => 401);
  }

  return 1; # Indicate success
};

under sub {
  my $c = shift;
  return $c->validate_shared_secret;
};

get '/protected' => sub {
  my $c = shift;
  $c->render(json => {message => 'Access granted'});
};

app->start;
```

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