---
title: "Add JWT Authentication to Your undefined API"
description: undefined
canonicalUrl: "https://zuplo.com/use-cases/api-key-auth/dart/shelf/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 'dart:async';
import 'dart:convert';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:jose/jose.dart';
import 'package:http/http.dart' as http;

const String issuer = 'https://my-api-a32f34.zuplo.api/__zuplo/issuer';
const String jwksUrl = '$issuer/.well-known/jwks.json';

// JWKS client to fetch public keys
Future<JsonWebKeyStore> fetchJwks() async {
  final response = await http.get(Uri.parse(jwksUrl));
  if (response.statusCode != 200) {
    throw Exception('Failed to load JWKS');
  }

  final jwks = JsonWebKeyStore()..addKeySet(JsonWebKeySet.fromJson(json.decode(response.body)));
  return jwks;
}

// Middleware to validate JWT
Middleware validateJwt(JsonWebKeyStore keyStore) {
  return (Handler innerHandler) {
    return (Request request) async {
      final authHeader = request.headers['Authorization'];
      if (authHeader == null || !authHeader.startsWith('Bearer ')) {
        return Response.forbidden('No token provided');
      }

      final token = authHeader.substring(7);
      try {
        final jwt = JsonWebSignature.fromCompactSerialization(token);
        final verified = await jwt.verify(keyStore, allowedAlgorithms: ['RS256']);
        if (!verified) {
          return Response.forbidden('Invalid token');
        }

        final claims = jwt.unverifiedPayload;
        request = request.change(context: {'user': claims});

        return innerHandler(request);
      } on Exception catch (e) {
        return Response.forbidden('Invalid token: ${e.toString()}');
      }
    };
  };
}

void main() async {
  final keyStore = await fetchJwks();

  final handler = const Pipeline()
      .addMiddleware(logRequests())
      .addMiddleware(validateJwt(keyStore))
      .addHandler((Request request) {
    final user = request.context['user'];
    return Response.ok('Access granted. User: ${user}');
  });

  final server = await shelf_io.serve(handler, 'localhost', 8080);
  print('Server running on localhost:${server.port}');
}
```

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