oauth2-server covers the RFCs and names no storage backend
A spec compliant, secure by default PHP OAuth 2.0 Server
At a glance
- What is it?
- league/oauth2-server is a PHP implementation of an OAuth 2.0 authorization server covering five RFCs and six grants. It takes PSR-7 messages, requires PHP 8.2 or newer, and its README names no storage backend.
- Who is it for?
- league/oauth2-server is the right pick when you need RFC level OAuth 2.0 behaviour in PHP and want to own the storage and routing decisions yourself. It is the wrong pick when a framework integration would carry that wiring for you, or when your application cannot move to PHP 8.2.
- Can I use it commercially?
- Yes. MIT 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 20 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 November 14, 2026, and from our analysis. They are not legal advice.
Star history
- thephpleague/oauth2-server6,675 ★ · +9
| Repository | 2026-09-23 | 2026-11-14 |
|---|---|---|
| thephpleague/oauth2-server | 6.7k | 6.7k |
9 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Six grants and five RFCs decide what you build around
The scope arrives as two lists. Out of the box the server supports six grants: the authorization code grant, the client credentials grant, the device authorization grant, the implicit grant, the refresh grant and the resource owner password credentials grant. Underneath sit five RFCs. RFC6749 is OAuth 2.0 itself, RFC6750 covers bearer token usage, RFC7519 covers JSON Web Tokens, RFC7636 is proof key for code exchange by OAuth public clients, and RFC8628 is the device authorization grant.
Two of those titles carry more weight than the rest. Proof key for code exchange by OAuth public clients is there for callers that cannot keep a secret, and the device authorization grant is there for devices that have no browser to redirect. Their presence tells you the package is aimed at native and device clients, not only at server to server traffic.
One caveat on the grant list. The README presents the six as a set the library supports out of the box and says only that a server can be configured, without describing a per grant switch. Finding out which grants your deployment can actually turn off means reading the documentation at oauth2.thephpleague.com, not the README.
PHP 8.2 is the floor and every request has to be PSR-7
Two requirements decide whether your application can adopt this without a refactor. The first is the PHP version. The latest package supports PHP 8.2, 8.3, 8.4 and 8.5, so an application still on 8.0 or 8.1 is out, and the `openssl` and `json` extensions have to be present alongside it. The second is the shape of the traffic. All HTTP messages passed to the server should be PSR-7 compliant, which the README presents as a deliberate choice for interoperability with other packages and frameworks.
That second requirement is the one that gets underestimated. The library does not read PHP globals and it does not bind to a framework router. It consumes request and response objects. If your application already runs on a PSR-7 stack, the adapter costs you nothing. If it does not, an object graph has to exist before any grant can run, and the README points you to the documentation site rather than naming which framework adapters ship in the box.
composer require, then vendor/bin/phpunit
The entire installation is one composer line, and it names the packagist package rather than the repository name:
composer require league/oauth2-serverThe package resolves as `league/oauth2-server` even though the repository is `thephpleague/oauth2-server`, so look it up by the package name when you search.
The first thing worth running after install is the test suite, which the project drives with PHPUnit:
vendor/bin/phpunitIts configuration sits in `phpunit.xml.dist` at the repository root, alongside `phpcs.xml.dist` for coding standards and `phpstan.neon.dist` for static analysis. Continuous integration runs GitHub Actions, Scrutinizer and StyleCI, configured from `.github/workflows/tests.yml`, `.scrutinizer.yml` and `.styleci.yml`. It is the project's own quality gate, a signal about how the library is checked.
The examples directory is its own composer project with a public web root
The repository ships an `examples/` directory that is more than a folder of snippets, and its layout shows how the library expects to sit inside an application. `examples/composer.json` and `examples/composer.lock` make it a self contained composer project, so the example carries its own dependency set rather than inheriting the root one. `examples/src/` holds the server side code, and `examples/public/` is the web root, the conventional place for a front controller that hands a library a request object.
What the layout confirms is that the package is meant to run behind an entry point producing PSR-7 messages, not inside a console command. What it does not tell you is which grants the example configures or how it stores tokens. Nothing in the README explains that, so `examples/README.md` is the file to read first before borrowing any of it.
No storage backend is named, so clients and tokens are yours to keep
The most consequential thing the README does not say is where grants live. No storage backend is named, and the repository tree carries no migrations and no schema directory. At the root the only code directories are `src/` and `tests/`, everything else being tooling configuration, `composer.json`, the licence and the contributing files.
An authorization server has to remember its clients, their permitted grants and their redirect URIs, and it has to remember issued access and refresh tokens until they expire. The README does not say how the package stores any of that, so check the documentation at oauth2.thephpleague.com before planning storage.
Laravel Passport and the Symfony bundle sit on top rather than beside it
The project names six community integrations: Drupal's `simple_oauth`, Laravel Passport, an OAuth 2 server for CakePHP 3, one for Mezzio, the Symfony `oauth2-server-bundle`, and Heimdall for CodeIgniter 4. All of them are built on this library, and the fork in the road they describe is concrete.
Taking the package directly means you write the PSR-7 wiring, the grant configuration and the storage yourself, and you keep full visibility of what your token endpoint does. Taking a framework integration means the framework supplies that wiring, and you accept its configuration conventions and its release cycle as the thing you have to track alongside the library. The integrations also decide the upgrade question for you: a bump that is uneventful in isolation becomes a coordination problem once a framework package sits between you and it.
Security reports bypass the tracker, and a Mozilla fund paid for the audit
Security handling is spelled out with unusual clarity. Bugs and feature requests are tracked on GitHub, but security related issues are asked to go by email to `[email protected]` instead, and questions about OAuth are asked to become tickets rather than reach that same address. Keeping vulnerability reports out of a public tracker is the sensible default, and the practical consequence is that you will not see advisories appear as issues on the repository.
Two provenance facts close the picture. The Mozilla Secure Open Source Fund paid for a security audit of the library, and the initial code came out of the Linkey project, funded by JISC under its Access and Identity Management programme. Maintenance has not stopped: the project is not archived, the last push landed on 2026-10-25, and the three most recent releases are 9.4.1 on 2026-06-25, 9.4.0 on 2026-06-14 and 9.3.0 on 2025-11-25.
Editorial conclusion
league/oauth2-server is the right pick when you need RFC level OAuth 2.0 behaviour in PHP and want to own the storage and routing decisions yourself. It is the wrong pick when a framework integration would carry that wiring for you, or when your application cannot move to PHP 8.2. Its scope is both a strength and a cost: six grants and five RFCs are implemented, but the README names no storage backend for clients and tokens. Before adopting, check the documentation site for the grant configuration you intend to expose, and confirm your HTTP layer can hand the server PSR-7 messages.
Frequently asked questions
What is an OAuth 2.0 authorization server?
It is a server that issues access tokens on the terms of RFC6749 and lets clients refresh them. league/oauth2-server is the PHP implementation of that idea, released under the MIT license and implementing RFC6749, RFC6750, RFC7519, RFC7636 and RFC8628.
How do I implement an OAuth 2.0 server with league/oauth2-server?
Add the package with `composer require league/oauth2-server`, then configure the server and hand it PSR-7 request and response objects. The library documentation at oauth2.thephpleague.com carries the configuration details, and contributions to it go to the gh-pages branch.
How do I set up league/oauth2-server?
The package requires PHP 8.2, 8.3, 8.4 or 8.5 plus the openssl and json extensions, and every HTTP message passed to the server must be PSR-7 compliant. Setup documentation is at oauth2.thephpleague.com, and the repository's examples directory holds a self contained composer project with a public web root.
What is league/oauth2-server used for?
It protects an API with access tokens and lets clients request new ones and refresh them. Six grants ship out of the box, from the authorization code grant and client credentials grant through the device authorization grant, implicit grant, refresh grant and resource owner password credentials grant.
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/thephpleague-oauth2-server)Star history chart for your README
[](https://hysenlabs.com/projects/thephpleague-oauth2-server)Was this useful?