Back
Syntax
Study
Editor
Mode:
HTML
CSS
JavaScript
PHP
Reset
Run »
HTML / CSS / JS
<?php // Secure JWT handling with firebase/php-jwt use Firebase\JWT\JWT; use Firebase\JWT\Key; $privateKey = file_get_contents('/run/secrets/jwt_private_key'); // PEM RSA key $publicKey = file_get_contents('/run/secrets/jwt_public_key'); // --- ISSUE an access token (RS256 asymmetric signing) --- function issueAccessToken(int $userId, string $email): string { global $privateKey; $now = time(); $payload = [ 'iss' => 'https://api.example.com', // issuer 'aud' => 'https://app.example.com', // audience 'sub' => (string) $userId, // subject 'iat' => $now, // issued at 'exp' => $now + 900, // 15-minute expiry 'email' => $email, // Do NOT include: passwords, PII beyond what's needed, secrets ]; return JWT::encode($payload, $privateKey, 'RS256'); } // --- VERIFY a token (explicit algorithm — never accept 'alg' from header) --- function verifyAccessToken(string $token): object { global $publicKey; $decoded = JWT::decode($token, new Key($publicKey, 'RS256')); // Validate additional claims if ($decoded->iss !== 'https://api.example.com') { throw new \RuntimeException('Invalid issuer'); } if ($decoded->aud !== 'https://app.example.com') { throw new \RuntimeException('Invalid audience'); } return $decoded; } // --- Refresh token stored in HttpOnly cookie, not in JWT payload --- // Set-Cookie: refresh_token=<opaque_token>; HttpOnly; Secure; SameSite=Strict; Path=/auth/refresh
Result
Open