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 2d 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

33

—

LowBetter than 72% of packages

Maintenance42

Moderate activity, may be stable

Popularity4

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity66

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

482d 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

[kartik-v/yii2-password

Useful password strength validation utilities for Yii Framework 2.0

761.3M17](/packages/kartik-v-yii2-password)[vitalybaev/laravel5-dkim

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

3163.1k](/packages/vitalybaev-laravel5-dkim)

PHPackages © 2026

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