PHPackages                             rafalswierczek/jwt - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. rafalswierczek/jwt

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

rafalswierczek/jwt
==================

Simple JWT codebase

3.1(1y ago)06MITPHPPHP 8.3.\*

Since Sep 18Pushed 1y ago1 watchersCompare

[ Source](https://github.com/rafalswierczek/jwt)[ Packagist](https://packagist.org/packages/rafalswierczek/jwt)[ RSS](/packages/rafalswierczek-jwt/feed)WikiDiscussions main Synced 2w ago

READMEChangelog (6)Dependencies (4)Versions (7)Used By (0)

Simple JWS authentication codebase
==================================

[](#simple-jws-authentication-codebase)

[![Build](https://github.com/rafalswierczek/jwt/actions/workflows/php.yml/badge.svg)](https://github.com/rafalswierczek/jwt/actions/workflows/php.yml)

#### Take total control over JWS authentication with help of this repository.

[](#take-total-control-over-jws-authentication-with-help-of-this-repository)

Installation:
-------------

[](#installation)

> composer require rafalswierczek/jwt

Usage
-----

[](#usage)

*Remember that this library is a code base so treat it as your source code. Be aware of exceptions defined in the contract, catch them.*

*Nothing will work unless you have 100% awareness of the whole architecture you want to implement.*

### SYMMETRIC SIGNATURE SYSTEM:

[](#symmetric-signature-system)

- Keep your JWS secret very safely and share it between applications to let one JWS be used to authenticate with multiple applications. This is pretty much the only reason to use JWT system at all.
- In authentication server or auth module in monolith:
    - Create your own endpoint that will check user credentials and return generated JWS in successful response.
    - Create your own instances of `JWSIssuerInterface`, `JWSHeader` and `JWSPayload` and generate new JWS that should be returned in auth endpoint.
    - Create your own instance of `RefreshTokenProviderInterface` and generate new refresh token that should be returned together with JWS.
    - You **MUST** have 1 unique secret key per 1 refresh token. Store both in a table as unique index. If refresh token get hacked or someone using it should be banned then you cannot do anything by definition of JWT system. The only way to handle this situation is to invalidate secret key associated with refresh token in such table to prevent user from generating new JWS that should be valid for 3~15 minutes depending on security measures.

    ```
    // Issuer example:
    namespace YourApp\AuthServer\Infrastructure;

    use YourApp\AuthServer\Application\JWSIssuer;
    use YourApp\AuthServer\Domain\Header;
    use YourApp\AuthServer\Domain\Payload;
    use YourApp\AuthServer\Domain\User;
    use rafalswierczek\JWT\JWS\Enum\Header\AlgorithmType;
    use rafalswierczek\JWT\JWS\Enum\Header\TokenType;
    use rafalswierczek\JWT\JWS\Issuer\JWSIssuerInterface;
    use rafalswierczek\JWT\JWS\Model\JWSHeader;
    use rafalswierczek\JWT\JWS\Model\JWSPayload;
    use rafalswierczek\Uuid4\Uuid4Factory;

    final class RafalswierczekJWSIssuer implements JWSIssuer
    {
        public function __construct(private JWSIssuerInterface $issuer)
        {
        }

        public function issueToken(User $user): string
        {
            $header = Header::create();

            $payload = Payload::create(
                jwtId: Uuid4Factory::create()->toHex(),
                userId: $user->id,
            );

            return $this->issuer->generateCompactJWS(
                header: $this->mapHeader($header),
                payload: $this->mapPayload($payload, $user),
                secret: $_ENV['JWS_PRIVATE_KEY'],
            );
        }

        private function mapHeader(Header $header): JWSHeader
        {
            return new JWSHeader(
                tokenType: TokenType::from($header->typ),
                algorithmType: AlgorithmType::from($header->alg),
            );
        }

        private function mapPayload(Payload $payload, User $user): JWSPayload
        {
            return new JWSPayload(
                id: $payload->jti, // globally unique JWT id
                issuer: $payload->iss, // domain of auth server (might be the same as audience element)
                subject: $payload->sub, // user-uuid
                issuedAt: (new \DateTimeImmutable())->setTimestamp($payload->iat),
                expirationTime: (new \DateTimeImmutable())->setTimestamp($payload->exp),
                audience: $payload->aud, // ['yourdomain1.com', 'yourdomain2.com']
                data: ['user' => $user], // user metadata known to all audience applications
            );
        }
    }
    ```
- In every application that matches the audience:
    - Create your own authenticator and from there use your instance of `JWSVerifierInterface` to verify JWS from request header.
    - If JWS is expired (`JWSHasExpiredException`) try to request your auth server to generate new JWS using current refresh token. Return 403.
    - `JWSCompromisedSignatureException` is a red flag, most likely an attack or bug. Log it as error or alert and return 403.
    - `CannotMatchAudienceException` Might be the problem with old domain name or the JWS is just not meant to be used for this specific application. Log it as warning and return 403.
    - If the refresh token is not valid, log off the user and force him to log in (auth server endpoint) using whatever credentials you use.

###  Health Score

32

—

LowBetter than 69% of packages

Maintenance39

Infrequent updates — may be unmaintained

Popularity4

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity67

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~180 days

Recently: every ~220 days

Total

6

Last Release

527d ago

Major Versions

1.1 → 2.02024-01-10

2.5 → 3.02024-08-04

### Community

Maintainers

![](https://www.gravatar.com/avatar/25b0d337f0f34a08f6adcf9603a9f4f942326d7794bdc9287a320a3284e10f10?d=identicon)[rafalswierczek](/maintainers/rafalswierczek)

---

Top Contributors

[![rafalswierczek](https://avatars.githubusercontent.com/u/37018158?v=4)](https://github.com/rafalswierczek "rafalswierczek (30 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/rafalswierczek-jwt/health.svg)

```
[![Health](https://phpackages.com/badges/rafalswierczek-jwt/health.svg)](https://phpackages.com/packages/rafalswierczek-jwt)
```

###  Alternatives

[tg/tgwebvalid

An easy way to validate Telegram Login Widget and Telegram Mini App users on your website using PHP

6827.5k1](/packages/tg-tgwebvalid)[vitalybaev/laravel5-dkim

Laravel 5/6 package for signing outgoing messages with DKIM.

3163.1k](/packages/vitalybaev-laravel5-dkim)[kissdigital-com/apple-sign-in-client-secret-generator

PHP package for generating 'client secret' for Sign In with Apple

2125.5k](/packages/kissdigital-com-apple-sign-in-client-secret-generator)[denniseilander/laravel-passport-scopes-restriction

Restrict scopes for different Laravel Passport clients.

1636.3k](/packages/denniseilander-laravel-passport-scopes-restriction)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
