'; const AUDIENCE = ''; const JWKS_URL = ISSUER . '/.well-known/jwks.json'; // CachedKeySet fetches once, caches to PSR-6, honours HTTP cache headers. $factory = new HttpFactory(); $cache = new FilesystemAdapter('codeb-jwks', 600, sys_get_temp_dir()); $keys = new CachedKeySet(JWKS_URL, new \GuzzleHttp\Client(), $factory, $cache, 600, true); function verify(string $token, $keys): array { JWT::$leeway = 5; $claims = (array) JWT::decode($token, $keys); if (($claims['iss'] ?? '') !== ISSUER) throw new RuntimeException('bad iss'); if (($claims['aud'] ?? '') !== AUDIENCE) throw new RuntimeException('bad aud'); return $claims; } // Example $claims = verify($argv[1], $keys); printf("sub = %s\nrole = %s\n", $claims['sub'], $claims['role'] ?? 'user'); // RFCs: 7519 (JWT), 7517 (JWK), 7518 (JWA).