Framework agnostic JWT library for PHP.

Maintainers

Package info

github.com/aleksandarjockovic226/jwt-package

pkg:composer/aleksandarjockovic226/php-jwt

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-06-22 08:07 UTC

This package is auto-updated.

Last update: 2026-06-22 08:23:08 UTC


README

Simple, framework-agnostic JWT library for PHP with RS256 support.

Features

  • JWT encoding and decoding
  • RS256 signing and verification
  • Custom key providers
  • Token validation
  • Expiration (exp) validation
  • Issued At (iat) validation
  • Not Before (nbf) validation
  • Framework agnostic
  • Fully typed (strict_types=1)
  • PHPUnit tested
  • PHPStan clean

Installation

composer require aleksandarjockovic226/php-jwt

Generate RSA Keys

Generate a private key:

openssl genrsa -out private.pem 2048

Generate the corresponding public key:

openssl rsa -in private.pem -pubout -out public.pem

Basic Usage

Create JWT Service

use aleksandarjockovic226\Jwt\Algorithms\RsaSha256Algorithm;
use aleksandarjockovic226\Jwt\Factories\DefaultJwtHeaderFactory;
use aleksandarjockovic226\Jwt\Providers\FileKeyProvider;
use aleksandarjockovic226\Jwt\Services\JwtService;
use aleksandarjockovic226\Jwt\Support\TokenParser;

$jwt = new JwtService(
    algorithm: new RsaSha256Algorithm(
        new FileKeyProvider(
            privateKeyPath: __DIR__ . '/private.pem',
            publicKeyPath: __DIR__ . '/public.pem',
        ),
    ),
    headerFactory: new DefaultJwtHeaderFactory(),
    tokenParser: new TokenParser(),
);

Encode Token

use aleksandarjockovic226\Jwt\Builders\JwtPayloadBuilder;

$payload = JwtPayloadBuilder::create()
    ->claim('sub', 123)
    ->claim('email', 'john@example.com')
    ->claim('role', 'admin')
    ->build();

$token = $jwt->encode($payload);

echo $token;

You can also set multiple claims at once with claims():

$payload = JwtPayloadBuilder::create()
    ->claims([
        'sub' => 123,
        'email' => 'john@example.com',
        'role' => 'admin',
    ])
    ->build();

Decode Token

$payload = $jwt->decode($token);

echo $payload->get('sub');
echo $payload->get('email');

Verify Token

$isValid = $jwt->verify($token);

if ($isValid) {
    echo 'Token is valid';
}

Using Expiration Validation

use aleksandarjockovic226\Jwt\Support\SystemClock;
use aleksandarjockovic226\Jwt\Validators\ExpirationValidator;

$jwt = new JwtService(
    algorithm: $algorithm,
    headerFactory: new DefaultJwtHeaderFactory(),
    tokenParser: new TokenParser(),
    validators: [
        new ExpirationValidator(
            new SystemClock(),
        ),
    ],
);

Generate token:

$payload = JwtPayloadBuilder::create()
    ->claim('sub', 123)
    ->claim('exp', time() + 3600)
    ->build();

Using Issued At Validation

use aleksandarjockovic226\Jwt\Validators\IssuedAtValidator;

$jwt = new JwtService(
    algorithm: $algorithm,
    headerFactory: new DefaultJwtHeaderFactory(),
    tokenParser: new TokenParser(),
    validators: [
        new IssuedAtValidator(
            new SystemClock(),
        ),
    ],
);
$payload = JwtPayloadBuilder::create()
    ->claim('iat', time())
    ->build();

Using Not Before Validation

use aleksandarjockovic226\Jwt\Validators\NotBeforeValidator;

$jwt = new JwtService(
    algorithm: $algorithm,
    headerFactory: new DefaultJwtHeaderFactory(),
    tokenParser: new TokenParser(),
    validators: [
        new NotBeforeValidator(
            new SystemClock(),
        ),
    ],
);
$payload = JwtPayloadBuilder::create()
    ->claim('nbf', time() + 60)
    ->build();

The token will become valid after 60 seconds.

Combining Validators

$jwt = new JwtService(
    algorithm: $algorithm,
    headerFactory: new DefaultJwtHeaderFactory(),
    tokenParser: new TokenParser(),
    validators: [
        new ExpirationValidator(
            new SystemClock(),
        ),
        new IssuedAtValidator(
            new SystemClock(),
        ),
        new NotBeforeValidator(
            new SystemClock(),
        ),
    ],
);

In-Memory Keys

Useful when keys are stored in environment variables or secrets managers.

use aleksandarjockovic226\Jwt\Providers\InMemoryKeyProvider;

$keyProvider = new InMemoryKeyProvider(
    privateKey: getenv('JWT_PRIVATE_KEY'),
    publicKey: getenv('JWT_PUBLIC_KEY'),
);

Access Payload Claims

$payload->has('email');

$payload->get('email');

$payload->get('missing', 'default-value');

$payload->all();

Exceptions

The package throws specialized exceptions:

JwtException
├── InvalidTokenException
├── InvalidHeaderException
├── InvalidPayloadException
├── InvalidSignatureException
├── TokenExpiredException
├── InvalidClaimException
├── KeyException
└── AlgorithmException

Example:

try {
    $payload = $jwt->decode($token);
} catch (TokenExpiredException $e) {
    echo 'Token expired';
} catch (InvalidSignatureException $e) {
    echo 'Invalid signature';
}

Requirements

  • PHP 8.5+
  • OpenSSL extension

License

MIT License