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

# Secure Serverpod APIs with API Key Authentication

Secure your Serverpod API using a shared secret.

## How Zuplo Handles It

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

## Serverpod Backend Code

```dart
import 'package:serverpod/serverpod.dart';
import 'dart:convert';
import 'package:crypto/crypto.dart';

class MyEndpoint extends Endpoint {
  @override
  Future<void> initialize(Server server, String name) async {
    super.initialize(server, name);
    // Register the middleware
    server.defaultServer.middleware.add(_validateSharedSecret);
  }

  // Shared secret validation
  Future<void> _validateSharedSecret(Session session, Future<void> Function() next) async {
    final secretHeader = session.httpRequest.headers.value('x-shared-secret');
    final expectedSecret = const String.fromEnvironment('SHARED_SECRET');

    if (expectedSecret.isEmpty) {
      session.log.severe('Server configuration error: Missing SHARED_SECRET');
      throw HttpResponseException(HttpStatus.internalServerError, 'Server configuration error');
    }

    if (secretHeader == null) {
      throw HttpResponseException(HttpStatus.unauthorized, 'No secret provided');
    }

    final secretBytes = utf8.encode(secretHeader);
    final expectedSecretBytes = utf8.encode(expectedSecret);

    // Use timing-safe comparison
    if (secretBytes.length != expectedSecretBytes.length ||
        !ListEquality().equals(hmacSha256.convert(secretBytes).bytes,
                               hmacSha256.convert(expectedSecretBytes).bytes)) {
      throw HttpResponseException(HttpStatus.unauthorized, 'Invalid secret');
    }

    // Proceed to the next middleware or endpoint
    await next();
  }

  // Example protected route
  Future<String> protectedRoute(Session session) async {
    return 'Access granted';
  }
}
```

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