Signed Tokens (JWS)

Sign a Token with HMAC (HS256)

The simplest approach: a shared secret key is used to both sign and verify the token.

<?php

use Jose\Component\Core\AlgorithmManager;
use Jose\Component\Core\JWK;
use Jose\Component\Signature\Algorithm\HS256;
use Jose\Component\Signature\JWSBuilder;
use Jose\Component\Signature\Serializer\CompactSerializer;

require_once 'vendor/autoload.php';

// Create a symmetric key (shared secret)
$jwk = new JWK([
    'kty' => 'oct',
    'k' => base64_encode(random_bytes(32)), // 256-bit key
]);

$algorithmManager = new AlgorithmManager([new HS256()]);
$jwsBuilder = new JWSBuilder($algorithmManager);

$payload = json_encode([
    'iss' => 'https://my-app.example.com',
    'aud' => 'https://api.example.com',
    'sub' => 'user-42',
    'iat' => time(),
    'exp' => time() + 3600,
]);

$jws = $jwsBuilder
    ->create()
    ->withPayload($payload)
    ->addSignature($jwk, ['alg' => 'HS256'])
    ->build();

$token = (new CompactSerializer())->serialize($jws);
// eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL215LWFwcC...

Verify the Token


Sign a Token with RSA (RS256)

RSA keys allow the signer and the verifier to use different keys: a private key to sign, a public key to verify.

Verify with the Public Key


Sign a Token with Elliptic Curve (ES256)

ECDSA keys are smaller and faster than RSA for the same security level.

Verify with the Public Key


Sign a Token with EdDSA (Ed25519)

EdDSA with Ed25519 provides high performance and strong security. Requires the sodium extension.


The JWSLoader combines deserialization, header checking, and signature verification in a single step. This is the recommended approach for loading tokens.

After verifying the signature, you should also validate the claims (exp, iss, aud, etc.). See the Claim and Header Validation page.

Last updated

Was this helpful?