web-token/jwt-signature
JWT Signature component from the web-token JWT Framework. Provides tools to create and verify JWT signatures in PHP. Read-only split repo; contribute via the main jwt-framework project. Full docs at https://web-token.spomky-labs.com/
Install the Package
composer require web-token/jwt-signature
(Note: This is a low-level component; pair with web-token/jwt-framework for full JWT support.)
First Use Case: Verify a JWT Signature
use WebToken\JWT\Signature\Algorithm\HS256;
use WebToken\JWT\Signature\Signature;
$signature = new Signature(new HS256('your-secret-key'));
$isValid = $signature->verify(
'header.payload',
'signature',
'secret'
);
Where to Look First
src/Signature.php (core class for signing/verification).src/Algorithm/ (algorithm implementations like HS256, RS256, ES256).Use Case: Replace or extend Laravel’s default JWT validation (e.g., for tymon/jwt-auth or custom APIs).
Pattern: Middleware for Signature Verification
// app/Http/Middleware/VerifyJwtSignature.php
namespace App\Http\Middleware;
use Closure;
use WebToken\JWT\Signature\Algorithm\HS256;
use WebToken\JWT\Signature\Signature;
class VerifyJwtSignature
{
public function handle($request, Closure $next)
{
$token = $request->bearerToken();
if (!$token) {
return response()->json(['error' => 'Unauthorized'], 401);
}
[$header, $payload, $signature] = explode('.', $token);
$signatureVerifier = new Signature(new HS256(config('jwt.secret')));
$isValid = $signatureVerifier->verify($header . '.' . $payload, $signature, config('jwt.secret'));
if (!$isValid) {
return response()->json(['error' => 'Invalid signature'], 401);
}
return $next($request);
}
}
Register in app/Http/Kernel.php:
protected $routeMiddleware = [
'verify.jwt' => \App\Http\Middleware\VerifyJwtSignature::class,
];
Use Case: Use RSA/ECDSA for asymmetric signing (e.g., public/private key pairs).
Pattern: RSA Signature Verification
use WebToken\JWT\Signature\Algorithm\RS256;
use WebToken\JWT\Signature\Signature;
$privateKey = file_get_contents(storage_path('app/private.key'));
$publicKey = file_get_contents(storage_path('app/public.key'));
// Signing (server-side)
$signer = new Signature(new RS256($privateKey));
$signature = $signer->sign('header', 'payload', $privateKey);
// Verification (client/API)
$verifier = new Signature(new RS256($publicKey));
$isValid = $verifier->verify('header.payload', $signature, $publicKey);
Use Case: Validate JWT claims (e.g., exp, iss) after signature verification.
Pattern: Combine with lcobucci/jwt
use WebToken\JWT\Signature\Signature;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Validation\Constraint\IssuedBy;
use Lcobucci\JWT\Validation\Constraint\RelatedTo;
$token = 'header.payload.signature';
$signature = new Signature(new HS256('secret'));
$isValid = $signature->verify(explode('.', $token)[0] . '.' . explode('.', $token)[1], explode('.', $token)[2], 'secret');
if ($isValid) {
$jwt = (new Parser())->parse($token);
$constraint = new IssuedBy('https://your-issuer.com');
$constraint->validate($jwt, new \DateTimeImmutable());
}
Use Case: Cache public keys or pre-compile algorithms for high-throughput APIs.
Pattern: Lazy-Loaded Signature Verifier
class CachedSignatureVerifier
{
private $cache = [];
public function verify(string $token, string $algorithm, string $key)
{
$cacheKey = $algorithm . ':' . md5($key);
if (!isset($this->cache[$cacheKey])) {
$this->cache[$cacheKey] = new Signature($this->createAlgorithm($algorithm, $key));
}
return $this->cache[$cacheKey]->verify(...);
}
private function createAlgorithm(string $algorithm, string $key)
{
// Dynamically instantiate algorithm (e.g., HS256, RS256)
}
}
Use Case: Unit test signature validation without hitting external APIs.
Pattern: Mocked Signature Verification
use WebToken\JWT\Signature\Signature;
use PHPUnit\Framework\TestCase;
class JwtSignatureTest extends TestCase
{
public function testSignatureVerification()
{
$signature = new Signature(new HS256('secret'));
$validSignature = $signature->sign('header', 'payload', 'secret');
$this->assertTrue($signature->verify('header.payload', $validSignature, 'secret'));
// Test invalid signature
$this->assertFalse($signature->verify('header.payload', 'invalid.signature', 'secret'));
}
}
Algorithm Mismatch Errors
HS256 with an RSA key (or vice versa) throws cryptographic errors.// Correct: HS256 for symmetric (secret) keys
new HS256('secret')
// Correct: RS256 for asymmetric (private/public) keys
new RS256(file_get_contents('private.key'))
Base64URL Decoding
header.payload (not decoded) to verify():
// Wrong: Decoded strings
$signature->verify(base64_decode($header), base64_decode($signature), 'secret');
// Correct: Raw Base64URL strings
$signature->verify($header . '.' . $payload, $signature, 'secret');
Key Management
config() or environment variables:
$signature = new Signature(new HS256(config('jwt.secret')));
No Built-in JWT Parsing
header, payload, and signature.lcobucci/jwt:
function splitJwt(string $jwt): array
{
return explode('.', $jwt);
}
Algorithm Availability
ES384 may be missing).class ES384 extends AbstractAlgorithm
{
public function __construct(string $key) { /* ... */ }
public function sign(string $data, string $key) { /* ... */ }
public function verify(string $data, string $signature, string $key) { /* ... */ }
}
Enable OpenSSL Debugging
Add this to your php.ini or runtime to debug cryptographic errors:
openssl.cafile=/path/to/cert.pem
openssl.verify_mode=2
Or use PHP’s error logging:
error_reporting(E_ALL);
ini_set('display_errors', 1);
Validate JWT Structure
Use an online decoder (e.g., jwt.io) to verify the JWT’s header, `
How can I help you explore Laravel packages today?