Content · Web Development · PHP

Using JWT Safely in PHP

JWTs must have cryptographic signatures validated against pinned algorithms and trusted keys. A parsed token is not an authenticated token; require issuer, audience and expiry.

1 views Published Oct 17, 2026 Updated Oct 17, 2026 admin

JWTs must have cryptographic signatures validated against pinned algorithms and trusted keys.

What It Does


JWTs must have cryptographic signatures validated against pinned algorithms and trusted keys. The following examples distinguish a normal use case, a boundary case and a practical application.

Requirements and Compatibility


A validated JWT library and trusted signing public key; example claim checks are never a substitute for verifying signatures.

The JWT header and payload are not trustworthy before a pinned-algorithm cryptographic signature check, and decoded claims still need issuer/audience/time validation.

The code focuses on the core concept. Production implementation may also need routes, validation, persistence, authorization or deployment tooling.

Example 1: Basic Behavior


Install an audited JWT implementation; never implement signature verification with base64 decoding alone.

composer require firebase/php-jwt

This is a command-line example; use it in its appropriate file or shell, not in the PHP source editor.

Example 2: Another Case


Verify cryptographic signature with a server-chosen algorithm and then validate issuer, audience and expiry.

<?php
require __DIR__ . '/vendor/autoload.php';
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
$token = (string) ($_SERVER['HTTP_AUTHORIZATION'] ?? '');
$token = preg_replace('/^Bearer\s+/i', '', $token);
$publicKey = file_get_contents('/srv/secrets/jwt-public.pem');
if ($publicKey === false) throw new RuntimeException('Public key missing');
$claims = JWT::decode($token, new Key($publicKey, 'RS256'));
$now = time();
if ($claims->iss !== 'https://issuer.example.test' ||
    !in_array('api', (array) $claims->aud, true) ||
    ($claims->exp ?? 0) <= $now) throw new RuntimeException('Invalid token claims');

This example depends on an installed extension, third-party library or configured service and is not a standalone local test.

Practical Example: Putting It to Use


Time-based claims require explicit time-window validation after verified token decoding; keep accepted skew small.

<?php
$claims = ['iat' => time() - 5, 'nbf' => time() - 5, 'exp' => time() + 120];
$now = time(); $leeway = 30;
if ($claims['nbf'] > $now + $leeway || $claims['exp'] <= $now - $leeway) { throw new RuntimeException('Expired or premature token'); }
echo 'Time claims accepted';

Important Behavior and Edge Cases


A parsed token is not an authenticated token; require issuer, audience and expiry checks.

Comparison with Related Functions or Approaches


OptionWhat it means in practice
Using JWT Safely in PHPJWTs must have cryptographic signatures validated against pinned algorithms and trusted keys.
Related approachOpaque server-side tokens are simpler when distributed JWT claims are unnecessary.

Common Beginner Mistakes


MistakeCorrect approach
Ignoring the important boundary for Using JWT Safely in PHPA parsed token is not an authenticated token; require issuer, audience and expiry checks.
Assuming a related mechanism has the same behaviorOpaque server-side tokens are simpler when distributed JWT claims are unnecessary.

Key Takeaways


  • JWTs must have cryptographic signatures validated against pinned algorithms and trusted keys.
  • A parsed token is not an authenticated token; require issuer, audience and expiry checks.
  • Opaque server-side tokens are simpler when distributed JWT claims are unnecessary.

Before adapting these examples, verify the return values, test the failure paths and confirm that your application meets its security and environment requirements.

Share this resourceSend this page to someone who may find it useful.