lcobucci/jwt: a PHP library for JWT and JWS, and what it refuses to decide for you
A simple library to work with JSON Web Token and JSON Web Signature.
At a glance
- What is it?
- lcobucci/jwt is a Composer package for building and parsing JSON Web Tokens and JSON Web Signatures in PHP, based on RFC 7519. It handles the token format and the signature algorithm; the claims policy stays in your code.
- Who is it for?
- Adopt lcobucci/jwt when you want the JWT and JWS format handled in PHP and you are willing to write the claim policy yourself, which suits services that already own their authentication rules. Do not adopt it expecting a plug-in authentication layer: it ships no middleware, no user provider and no key store, so a Laravel or Symfony project normally pairs it with a framework-specific package instead.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What lcobucci/jwt actually takes off your plate
A JSON Web Token is three base64url segments joined by dots: a header naming the algorithm, a payload of claims, and a signature. Producing and verifying that structure correctly is fiddly in ways that do not show up until something goes wrong. The header must be encoded in a canonical form or the signature will not match. The signature input is the first two segments exactly as they were transmitted, not a re-serialisation of the decoded data. The library exists to own that byte-level work so application code never has to.
It is aimed at PHP developers who are already implementing authentication or token exchange and want the format handled by a library rather than by hand-rolled base64 and hash calls. The README describes it as "a simple library to work with JSON Web Token and JSON Web Signature based on the RFC 7519", and the word simple is load-bearing. It is a format library, not an authentication framework. It will sign a token for you and it will verify a signature for you. It will not decide that a token has expired, that its issuer is one you trust, or that its audience matches the service receiving it. Those are claims, and claims are your policy.
Keys, signers and the split between building and parsing
The public surface divides into two halves, and the repository layout makes that plain. Under src/ the library separates token construction from token consumption, with the signer and key abstractions sitting underneath both. A signer wraps a cryptographic algorithm and a key wraps the material that algorithm needs. You choose a signer for the algorithm you intend to use, pair it with a key, and hand both to the builder or the parser.
That split is the reason the library composes well with frameworks. The builder produces a token string; the parser takes a token string and gives you back a token object. Nothing in that path reads a configuration file, opens a database, or knows what a user is. The verification step is the same shape: the parser is given the keys it should accept, and it checks the signature against them. Everything after that, including every claim check, is code you write.
The trade-off is honest but real. A library that enforced exp and nbf and aud by default would be safer for newcomers and less useful for anyone with unusual rules. lcobucci/jwt takes the second position. The documentation site at lcobucci-jwt.readthedocs.io exists precisely because the library gives you primitives and expects you to assemble them, and the README points there rather than reproducing the guidance inline.
Installing lcobucci/jwt and issuing a first token
The package is on Packagist and installs through Composer. The README gives exactly one command for it:
composer require lcobucci/jwtThat pulls the library and its dependencies into vendor/ and updates composer.json and composer.lock. Because the repository ships a composer.lock and a Makefile target that runs composer install against it, you can also see how the maintainers pin their own development environment, which is a reasonable signal about how the project expects dependency resolution to behave.
After installation, the first real use is issuing a signed token. The README does not carry a code sample: it points to the documentation at lcobucci-jwt.readthedocs.io and stops there. So the honest starting point is that site, not a snippet lifted from a tutorial. The shape the library expects is consistent across versions: pick a signer for your algorithm, build a key from your secret or private key, configure the token, and sign it. The exact class names and factory methods differ between majors, which is why copying a snippet from an older article is a reliable way to spend an afternoon on a method that no longer exists. Check the documentation for the version you installed before you write anything.
The claim checks the library will not do for you
This is the limitation that matters most, and it is a design decision rather than an oversight. A token whose signature verifies is a token that was signed by a key you listed. It is not necessarily a token you should accept. The exp claim may have passed, the nbf claim may be in the future, the iss claim may name a different issuer entirely, and the aud claim may be for another service. None of that is checked by signature verification alone.
If you treat a successful parse as authentication, you have built a system where any token signed by a shared key is accepted by every service holding that key. In a single-service deployment with one secret that may be tolerable. In anything multi-tenant, or anything where one signing key is shared across services, it is a real vulnerability, and it is the most common way this class of library gets misused.
The second limitation is version churn. The default branch is 6.0.x while the most recent release listed is 5.6.0, which means the code you find in older blog posts and Stack Overflow answers is likely written against a different major version with different class names and factory methods.
How it differs from firebase/php-jwt and framework bundles
The closest general-purpose alternative is firebase/php-jwt, which solves the same format problem with a different API philosophy. Where lcobucci/jwt exposes signer and key objects and asks you to assemble a configuration, firebase/php-jwt leans toward static encode and decode calls that take the key and algorithm as arguments. The practical difference shows up in testing and in dependency injection: object-oriented signers and keys can be swapped for test doubles and wired through a container, while static calls are harder to substitute and tend to get wrapped in a thin service class anyway.
A different kind of alternative is a framework bundle. LexikJWTAuthenticationBundle for Symfony and the Laravel-oriented packages in the same space build on top of a JWT library and add the parts lcobucci/jwt deliberately omits: a security listener, a token extractor, a user provider hook, and configuration keys you set in YAML or a config file. If your framework has a maintained bundle, using the bundle and letting it depend on the underlying library is usually less work than wiring the primitives yourself.
The choice is therefore not about which library is better at cryptography. It is about how much of the authentication layer you want to own. Picking lcobucci/jwt means owning more of it.
Maintenance, licence and the cost of upgrading
The repository is not archived, and the last push on the default branch was on 2025-10-17, which is also the date of the 5.6.0 release. Earlier releases in the same series, 5.5.0 and 5.4.3, landed in January and February 2025. That pattern suggests a project that ships fixes and minor features rather than one that has been abandoned, but the cadence is modest, and you should plan around that rather than assume rapid turnaround on an issue you file.
The licence is BSD-3-Clause, which is permissive: you can use the library in closed-source products, and the main obligation is retaining the copyright notice and licence text. That is the plain reading of the identifier. It is not legal advice, and if you are redistributing the library in a product with unusual licensing constraints, have someone qualified read the LICENSE file in the repository.
The upgrade cost is worth budgeting for explicitly. The library has crossed major versions, and the default branch is already on 6.0.x while the newest published release is 5.6.0, so a migration from 5.x to 6.x is a code change rather than a version bump. The repository includes a backward compatibility check configuration at .roave-backward-compatibility-check.json, which indicates the maintainers track breaking changes deliberately. That is a good sign for predictability, and it also means the breaks are intentional and documented in release notes rather than accidental. Read those notes before upgrading.
Editorial conclusion
Adopt lcobucci/jwt when you want the JWT and JWS format handled in PHP and you are willing to write the claim policy yourself, which suits services that already own their authentication rules. Do not adopt it expecting a plug-in authentication layer: it ships no middleware, no user provider and no key store, so a Laravel or Symfony project normally pairs it with a framework-specific package instead. Before committing, verify three things against your PHP version and your framework: which signature algorithms your OpenSSL build actually exposes, whether your issuer and audience checks are enforced in code rather than assumed, and whether the version you pin still receives fixes, given the last push on the default branch was on 2025-10-17.
Frequently asked questions
What does JWT stand for?
JSON Web Token. The README describes lcobucci/jwt as a library to work with JSON Web Token and JSON Web Signature based on RFC 7519.
Can a JWT never expire?
The library does not enforce expiry for you, so a token without an exp claim will keep passing signature verification. Whether that is acceptable is a claim policy you write yourself, not something lcobucci/jwt decides.
Can I decode a JWT online?
That is outside this library's scope. lcobucci/jwt is a PHP package installed with composer require lcobucci/jwt, and the README points to the documentation site for usage rather than to any decoding tool.
What are the drawbacks of JWT?
For this library specifically, the drawback is that signature verification is not the same as accepting a token. Claims such as exp, iss and aud are not checked for you, so a successful parse only tells you the token was signed by a key you supplied.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/lcobucci-jwt)