lcobucci/jwt
64.4
Adequate · 26 September 2026
2.8k
lines of production code
PHP
primary language
4
measurements over time
What this system is
This system is a PHP library for creating, parsing, and validating JSON Web Tokens (JWTs) with a focus on security and immutability. It supports a wide range of cryptographic signing algorithms, including HMAC, RSA, ECDSA, EdDSA, and Blake2b, while providing a constraint-based API for validating token claims, signatures, and time-based validity. The library enforces strict type safety and key length requirements to prevent common security vulnerabilities.
How it got here
2014–2015 — API refactoring and cryptographic modernization
7 changes.
The project underwent a major architectural overhaul, introducing an immutable JWT builder and facade API to replace previous token construction mechanisms. This period also focused on modernizing the cryptographic backend by migrating ECDSA to OpenSSL, adding support for Blake2b and EdDSA, and enforcing stricter key length requirements for HMAC signers.
2017–2022 — JWT API redesign and hardening
14 changes.
The codebase underwent a comprehensive architectural overhaul to enforce immutability and strict typing across the JWT token model, builder, and key handling components. A new constraint-based validation API was introduced to replace previous validation methods, offering granular control over claim and signature verification. This period also focused on robustness and performance, adding extensive test coverage for all signing algorithms and benchmarking the token lifecycle.
Features
Added RSA signers for SHA-256, SHA-384, and SHA-512
New RSA signer classes (Sha256, Sha384, Sha512) have been added to the library, enabling JWT signing using the RS256, RS384, and RS512 algorithms. These classes extend the base Rsa signer and are implemented as final, readonly classes with strict typing enabled.
src/Signer/Rsa · high confidence
New JWT validation constraints and stricter time validation
The validation layer now includes new constraint classes for checking custom claims (HasClaim, HasClaimWithValue), audience (PermittedFor), issuer (IssuedBy), token ID (IdentifiedBy), and subject (RelatedTo). Time-based validation has been split into StrictValidAt, which requires the presence of standard registered claims (exp, nbf, iat) before validating them, and LooseValidAt, which validates time windows without requiring those claims. Signature verification is now handled by SignedWith, SignedWithUntilDate (which expires the constraint itself after a date), and SignedWithOneInSet (which allows verifying against multiple keys/algorithms). Additionally, using constraints for registered claims like 'iss' or 'aud' directly is now blocked in favor of the specific dedicated constraints.
src/Validation/Constraint · high confidence
New cryptographic signer implementations and infrastructure
The Signer component now includes new implementations for Blake2b, EdDSA, and HMAC-based signing, alongside refactored RSA and ECDSA signers that leverage OpenSSL. This change introduces a new Key interface, specific exception classes for invalid keys and signing errors, and an abstract OpenSSL base class to handle key validation and signature creation. Users gain support for additional algorithms (Blake2b, EdDSA) and more robust error handling for key compatibility and length requirements across all signer types.
src/Signer · high confidence
New encoding components and date formatting options
The src/Encoding directory now includes new classes for handling JWT encoding and claim formatting. JoseEncoder provides the core JSON and Base64Url encoding/decoding logic, utilizing a Sodium polyfill for Base64 operations. New formatter classes—MicrosecondBasedDateConversion, UnixTimestampDates, and UnifyAudience—allow for precise control over how date claims (converted to microsecond or integer Unix timestamps) and audience claims (unified from arrays to strings) are processed. These formatters can be combined via the new ChainedFormatter, which offers default configurations for both microsecond-based and Unix-timestamp-based date handling. Additionally, specific exception classes (CannotDecodeContent, CannotEncodeContent) have been introduced to provide clearer error reporting during encoding and decoding failures.
src/Encoding · high confidence
New validation API with constraint-based validation
The library introduces a new validation API in the \src/Validation\ namespace, replacing the previous validation approach. Users can now validate tokens using a \Validator\ class that accepts a \Token\ and a variadic list of \Constraint\ objects. The API includes a \Constraint\ interface with an \assert\ method, specific constraint interfaces like \SignedWith\ and \ValidAt\, and new exception classes (\ConstraintViolation\, \RequiredConstraintsViolated\, \NoConstraintsGiven\) to handle validation failures. The \Validator\ provides both \assert\ (throws on failure) and \validate\ (returns boolean) methods, allowing for more explicit and flexible token validation logic.
src/Validation · high confidence
Behavioural changes
ECDSA signers now use OpenSSL with a new signature conversion layer
The ECDSA signing implementation has been refactored to use OpenSSL for cryptographic operations instead of the previous PHPECC library. To support this, a new internal signature conversion component (MultibyteStringConverter) and associated exception class (ConversionFailed) have been added to handle the translation between OpenSSL's ASN.1 signature format and the concatenated R/S format required by the JWA specification. This change affects all existing ECDSA signer classes (Sha256, Sha256K, Sha384, Sha512), which now rely on this new conversion infrastructure.
src/Signer/Ecdsa · high confidence
HMAC signers now enforce minimum key lengths
The HMAC signer implementations (SHA-256, SHA-384, and SHA-512) now require a minimum key length, with specific bit requirements (256, 384, and 512 bits respectively) enforced via the \minimumBitsLengthForKey\ method. This change ensures that keys used for signing are sufficiently strong, improving security by preventing the use of weak or too-short keys.
src/Signer/Hmac · high confidence
Introduce InMemory key factory with strict non-empty validation and sensitive parameter protection
The library now provides an \InMemory\ class in the \Signer\\Key\ namespace to create key instances from plain text, base64-encoded strings, or file contents. This implementation enforces that key contents must be non-empty, throwing an \InvalidKeyProvided\ exception if an empty string is passed, and introduces a new \FileCouldNotBeRead\ exception for file-reading errors. Additionally, sensitive parameters like key contents and passphrases are marked with the \SensitiveParameter\ attribute to improve debug output security, and the class is defined as \readonly\ to ensure immutability.
src/Signer/Key · high confidence
Introduces new immutable JWT builder, parser, and facade architecture
The library has been refactored to use a new, immutable API structure. Users now build tokens via the new \Builder\ interface (accessed through \Configuration\ or \JwtFacade\) and parse/validate them using the new \Parser\ and \Validator\ components. The \JwtFacade\ provides a simplified entry point for issuing and parsing tokens with default constraints. This change replaces the previous token construction and validation mechanisms with a more explicit, chainable, and immutable design.
src · high confidence
JWT token model and builder restructured for immutability and strict typing
The token handling in src/Token has been completely rewritten to use immutable, readonly classes (Builder, Plain, DataSet, Signature) and enforce stricter type safety. The Builder now uses a named constructor and immutable claim-setting methods (e.g., withClaim, permittedFor), preventing modification of registered claims and ensuring signatures are always generated. Parsing now strictly validates JWT structure, converts date claims to DateTimeImmutable objects, and forces the audience claim to be an array, throwing specific exceptions for invalid structures or unsupported headers.
src/Token · high confidence
Project infrastructure and documentation overhaul
The repository has been restructured with new configuration files for static analysis (PHPStan level 8), coding standards (PHPCS with Lcobucci rules), and mutation testing (Infection with specific mutator exclusions). A Makefile was introduced to streamline development tasks, and documentation is now managed via MkDocs on ReadTheDocs. The README was updated with installation instructions, badges, and links to the new documentation site, while the LICENSE file had its copyright year updated.
(repo-wide) · high confidence
Test coverage
Add test fixtures for ECDSA and RSA key pairs; Added benchmark suite for JWT signing, verification, and token lifecycle; Added test coverage for ECDSA signers and curve validation; Added test coverage for JWT configuration, encoding, and signature algorithms; Added test coverage for JWT validation constraints; Added test coverage for RSA signers; Added unit tests for Blake2b and EdDSA signers; Added unit tests for InMemory key handling; Added unit tests for Token component classes.
Dependencies
Initial release with PHP 8.4/8.5 support and modernized tooling
The project now requires PHP 8.4 or 8.5 and mandates the OpenSSL and Sodium extensions. Development tooling has been upgraded to PHPUnit 13, PHPStan 2, and Infection 0.35, with coding standards managed by lcobucci/coding-standard 12. The library also introduces a hard dependency on psr/clock 1.0 for time handling.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.
Score
- CAI 43 → 64 (+21.1)
- Rubric changed (rubric-2026.08.15 → rubric-2026.09.15) — scores are not directly comparable.
Lenses
- Code Health 100 → 100 (-0.3)
- Architecture 94 → 95 (+0.5)
- Maturity 54 → 51 (-2.9)
- Readiness 32 → 78 (+45.7)
- Security 33 → 66 (+33.2)
Resolved (37)
- Coverage not measured — test suite did not build
- Dimension evaluation failed
- Disclosure policy has no reporting contact
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- …and 17 more
New (62)
- Disclosure policy routes reports to a public channel
- Documentation: no installation or build instructions (README.md)
- Duplicate Builder creation mechanisms with inconsistent signatures. Configuration provides a factory method builder() that returns a Builder instance, while Token.Builder exposes a static-style factory method new(). Furthermore, Configuration.builder() accepts an optional ClaimsFormatter, whereas Token.Builder.new() requires an Encoder and a ClaimsFormatter. This creates confusion about which entry point to use for creating a builder and what dependencies are required.
- Duplicate Validator types. Lcobucci.JWT.Validation.Validator and Lcobucci.JWT.Validator have identical method signatures (assert and validate). This suggests a namespace duplication or a legacy alias that has not been cleaned up, causing confusion about which class to instantiate or type-hint against.
- Duplicated block (9 lines × 2) (src/Encoding/MicrosecondBasedDateConversion.php)
- Duplicated block (9 lines × 2) (src/Validation/Constraint/LooseValidAt.php)
- High CVE: [GHSA redacted] (composer.lock)
- High interface indirection
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- …and 42 more
Changes since last survey
- 26 commits — 26 feature/other, 0 fixes
By area
- (root) — 20 commits
- .github/workflows — 4 commits
- (repo) — 1 commit
- docs/supported-algorithms.md — 1 commit
Notable commits
- change: Ignore ProtectedVisibility mutant on OpenSSL::guardAgainstIncompatibleCurve
- change: Implement ES256K signer support
- change: Reorganize algorithm documentation
- change: Update codecov/codecov-action action to v7.1.0
- change: Update codecov/codecov-action action to v7.1.1
- change: Update dependency infection/infection to ^0.35.0
- change: Update dependency infection/infection to v0.34.2
- change: Update dependency infection/infection to v0.35.2
- change: Update dependency infection/infection to v0.35.3
- change: Update dependency infection/infection to v0.35.4
- change: Update dependency phpstan/phpstan to v2.2.10
- change: Update dependency phpstan/phpstan to v2.2.11
- change: Update dependency phpstan/phpstan to v2.2.12
- change: Update dependency phpstan/phpstan to v2.2.13
- change: Update dependency phpstan/phpstan to v2.2.14
- change: Update dependency phpstan/phpstan to v2.2.15
- change: Update dependency phpstan/phpstan to v2.2.16
- change: Update dependency phpstan/phpstan to v2.2.9
- change: Update dependency phpunit/phpunit to v13.3.0
- change: Update dependency phpunit/phpunit to v13.3.1
- …and 6 more
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
lcobucci/jwt was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 26 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 7c8ce003c5a94fd8fc4b61e3c6924b950ca3299c — the exact code this score is about.
- Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-a15879f6f801.