---
title: "Add JWT Authentication to Your Lumen API"
description: "Secure your Lumen API using JWT authentication with JWKS."
canonicalUrl: "https://zuplo.com/use-cases/api-key-auth/php/lumen/jwt-backend"
framework: "Lumen"
language: "PHP"
authStrategy: "JWT with JWKS"
pageType: use-case
---

# Add JWT Authentication to Your Lumen API

Secure your Lumen API using JWT authentication with JWKS.

## How Zuplo Handles It

Let Zuplo issue short-lived JWTs signed with a JWKS your Lumen backend can verify — no long-lived API keys touch your origin.

## Lumen Backend Code

```php
<?php

// app/Http/Middleware/JwtAuthMiddleware.php
namespace App\Http\Middleware;

use Closure;
use Firebase\JWT\JWT;
use Firebase\JWT\JWK;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;

class JwtAuthMiddleware
{
    private const ISSUER = 'https://my-api-a32f34.zuplo.api/__zuplo/issuer';
    private const JWKS_URI = self::ISSUER . '/.well-known/jwks.json';

    public function handle(Request $request, Closure $next)
    {
        $authHeader = $request->header('Authorization');

        if (!$authHeader || !str_starts_with($authHeader, 'Bearer ')) {
            return response()->json(['error' => 'No token provided'], 401);
        }

        $token = substr($authHeader, 7);

        try {
            $jwks = $this->fetchJwks();
            $decoded = JWT::decode($token, JWK::parseKeySet($jwks), ['RS256']);

            if ($decoded->iss !== self::ISSUER) {
                return response()->json(['error' => 'Invalid issuer'], 401);
            }

            $request->attributes->set('user', $decoded);
            return $next($request);
        } catch (\Exception $e) {
            return response()->json([
                'error' => 'Invalid token',
                'details' => $e->getMessage()
            ], 401);
        }
    }

    private function fetchJwks(): array
    {
        return Cache::remember('jwks', 600, function () {
            $response = file_get_contents(self::JWKS_URI);
            return json_decode($response, true);
        });
    }
}

// bootstrap/app.php
// $app->routeMiddleware(['jwt' => App\Http\Middleware\JwtAuthMiddleware::class]);

// routes/web.php
// $router->get('/protected', ['middleware' => 'jwt', function (Request $request) {
//     return response()->json([
//         'message' => 'Access granted',
//         'user' => $request->attributes->get('user')
//     ]);
// }]);
```

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