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

```php
use Yii;
use yii\filters\auth\AuthMethod;
use Firebase\JWT\JWT;
use Firebase\JWT\JWK;
use GuzzleHttp\Client;

class JwtAuth extends AuthMethod
{
    public $issuer = "https://my-api-a32f34.zuplo.api/__zuplo/issuer";
    private $jwksUri;
    private $httpClient;

    public function init()
    {
        parent::init();
        $this->jwksUri = "{$this->issuer}/.well-known/jwks.json";
        $this->httpClient = new Client(['cache' => true, 'cache_ttl' => 600]);
    }

    public function authenticate($user, $request, $response)
    {
        $authHeader = $request->getHeaders()->get('Authorization');
        if ($authHeader !== null && preg_match('/^Bearer\s+(.*?)$/', $authHeader, $matches)) {
            $token = $matches[1];
            try {
                $keys = $this->getJWKSKeys();
                $decoded = JWT::decode($token, JWK::parseKeySet($keys), ['RS256']);

                if ($decoded->iss !== $this->issuer) {
                    throw new \Exception('Invalid issuer');
                }

                $identity = $user->loginByAccessToken($token, get_class($this));
                if ($identity === null) {
                    $this->handleFailure($response);
                }
                return $identity;

            } catch (\Exception $e) {
                $response->setStatusCode(401);
                return $response->data = ['error' => 'Invalid token', 'details' => $e->getMessage()];
            }
        }
        return null;
    }

    protected function getJWKSKeys()
    {
        $response = $this->httpClient->get($this->jwksUri);
        return json_decode($response->getBody(), true);
    }
}

// Example usage in a controller
public function behaviors()
{
    $behaviors = parent::behaviors();
    $behaviors['authenticator'] = [
        'class' => JwtAuth::class,
    ];
    return $behaviors;
}

public function actionProtected()
{
    return [
        'message' => 'Access granted',
        'user' => Yii::$app->user->identity,
    ];
}
```

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