---
title: "Add JWT Authentication to Your undefined API"
description: undefined
canonicalUrl: "https://zuplo.com/use-cases/api-key-auth/dart/serverpod/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

```dart
import 'package:serverpod/serverpod.dart';
import 'package:jose/jose.dart';
import 'package:http/http.dart' as http;

class AuthEndpoint extends Endpoint {
  // Replace with your actual Zuplo deployment name or custom domain
  static const String issuer = 'https://my-api-a32f34.zuplo.api/__zuplo/issuer';
  static const String jwksUri = '$issuer/.well-known/jwks.json';

  // Fetch JWKS
  Future<JsonWebKeyStore> _getKeyStore() async {
    final response = await http.get(Uri.parse(jwksUri));
    if (response.statusCode != 200) {
      throw Exception('Failed to load JWKS');
    }
    // Parse JWKS
    final keyStore = JsonWebKeyStore()
      ..addKeySet(JsonWebKeySet.fromJson(response.body));
    return keyStore;
  }

  // JWT Validator
  Future<bool> _validateJwt(String? token) async {
    if (token == null) return false;

    try {
      final jwt = JsonWebToken.unverified(token);
      final keyStore = await _getKeyStore();

      final verified = await keyStore.verify(jwt) &&
          jwt.claims.issuer == issuer &&
          jwt.claims.isValidAudience('your-audience') &&
          jwt.claims.isNotExpired;

      return verified;
    } catch (e) {
      print('JWT validation error: $e');
      return false;
    }
  }

  // Middleware
  Future<bool> validateSession(Session session, Future<void> Function() next) async {
    final authHeader = session.httpRequest.headers['authorization']?.first;
    final token = authHeader?.replaceFirst('Bearer ', '');

    if (await _validateJwt(token)) {
      return next();
    } else {
      session.sendHttpStatus(401);
      session.write('Invalid token');
      return false;
    }
  }

  // Protected Endpoint
  @override
  void initialize(Server server) {
    server.registerRoute(RouteDefinition(
      method: HttpMethod.get,
      path: 'protected',
      handler: (session) async {
        session.write('Access granted');
      },
      requestFilter: validateSession,
    ));
  }
}
```

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