NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Packagist · #258 most downloaded on Packagist
A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.
Last release 3 months ago
25 Jun 2026
Release timing varies
gaps range from 2 weeks to 9 months
Nearly every release is documented
notes for 57 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
14 years old
116 releases · first in 2012
Removed the dependency on Lcobbuci's Clock to avoid conflicts with other clock implemenations in user land (PR #1505 )
Authorization requests are now checked for the required response_type parameter before we determine which grant type is being used (PR #1507 )
One column per quarter.
Added sensitive parameter to avoid sensitive data being included in stack traces (PR #1483 )
Added a new function to the provided ClientTrait, supportsGrantType to allow the auth server to issue the response unauthorized_client when applicable
supportsGrantType to allow the auth server to issue the response unauthorized_client when applicable (PR #1420)slow_down error happens, because the exception is thrown before calling persistDeviceCode. (PR #1410)slow_down error response may have been returned even after the user has completed the auth flow (already approved / denied the request). (PR #1410)RequestAccessTokenEvent and RequestRefreshTokenEvent events instead of the general RequestEvent event when an access / refresh token is issued using device authorization grant. (PR #1467)supportsGrantType to allow the auth server to issue the response unauthorized_client when applicable (PR #1420)slow_down error happens, because the exception is thrown before calling persistDeviceCode. (PR #1410)slow_down error response may have been returned even after the user has completed the auth flow (already approved / denied the request). (PR #1410)RequestAccessTokenEvent and RequestRefreshTokenEvent events instead of the general RequestEvent event when an access / refresh token is issued using device authorization grant. (PR #1467)Support for PHP 8.4 (PR #1454 )
Auto-generated event emitter is now persisted. Previously, a new emitter was generated every time (PR #1428 )
invalid_scope error response and wasn't on fragment part of access_denied redirect URI on Implicit grant (PR #1298)revokeRefreshTokens(false) unintentionally disables issuing new refresh token (PR #1449)Device Authorization Grant added (PR #1074 )
revokeRefreshTokens() for enabling or disabling refresh tokens after use (PR #1375)getKeyContents() to the CryptKeyInterface (PR #1375)invalid_grant error and a HTTP 400 response. In previous versions the server incorrectly issued an invalid_request and HTTP 401 response (PR #1042) (PR #1082)createAuthorizationRequest() (PR #1111)finalizeScopes() to allow a reference to an auth code ID (PR #1112)toString() instead of the magic method __toString() (PR #1395)Device Authorization Grant added (PR #1074 )
revokeRefreshTokens() for enabling or disabling refresh tokens after use (PR #1375)getKeyContents() to the CryptKeyInterface (PR #1375)invalid_grant error and a HTTP 400 response. In previous versions the server incorrectly issued an invalid_request and HTTP 401 response (PR #1042) (PR #1082)createAuthorizationRequest() (PR #1111)finalizeScopes() to allow a reference to an auth code ID (PR #1112)toString() instead of the magic method __toString() (PR #1395)PHP 8.4 deprecation notices fixed (PR #1466 )
Support for league/uri ^7.0 (PR #1367)
If a key string is provided to the CryptKey constructor with an invalid passphrase, the LogicException message generated will expose the given key. Th
Bumped the versions for laminas/diactoros and psr/http-message to support PSR-7 v2.0 (PR #1339)
Fixed PHP version constraints and lcobucci/clock version constraint to support PHP 8.1 (PR #1336)
Support for PHP 8.1 and 8.2 (PR #1333)
PHP 8.4 deprecation notices fixed (PR #1466 )
Nothing published for this version
Fix deprecation notices for PHP 8.x (PR #1329)
You can now set a leeway for time drift between servers when validating a JWT (PR #1304)
Use LooseValidAt instead of StrictValidAt so that users aren't forced to use claims such as NBF in their JWT tokens (PR #1312)
Use InMemory::plainText('empty', 'empty') instead of InMemory::plainText('') to avoid new empty string exception thrown by lcobucci/jwt (PR #1282)
Server previously rejected valid uris with custom schemes. Now use league/uri for parsing to accept all valid uris (PR #1274)
Removed the use of LocalFileReference() in lcobucci/jwt. Function deprecated as per GHSA-7322-jrq4-x5hf (PR #1249)
LocalFileReference() in lcobucci/jwt. Function deprecated as per GHSA-7322-jrq4-x5hf (PR #1249)Conditionally support the StrictValidAt() method in lcobucci/jwt so we can use version 4.1.x or greater of the library (PR #1236)
StrictValidAt() method in lcobucci/jwt so we can use version 4.1.x or greater of the library (PR #1236)Revert check on clientID. We will no longer require this to be a string (PR #1233)
The server will now validate redirect uris according to rfc8252 (PR #1203)
revokeRefreshTokens() function to decide whether refresh tokens are revoked or not upon use (PR #1189)openssl_pkey_get_private() and openssl_pkey_get_public() instead of regex matching (PR #1215)empty() check (PR #1181)Reverted the enforcement of at least one redirect_uri for a client. This change has instead been moved to version 9 (PR #1169)
Re-added support for PHP 7.2 (PR #1165, #1167)
Fix issue where the private key passphrase isn't correctly passed to JWT library (PR #1164)
If you have a password on your private key, it is now passed correctly to the JWT configuration object. (PR #1159)
Add a getRedirectUri function to the OAuthServerException class (PR #1123)
getRedirectUri function to the OAuthServerException class (PR #1123)code_challenged changed to code_challenge. Thrown by Auth Code Grant when the code challenge does not match the regex. (PR #1130)If you provide a valid redirect_uri with the auth code grant and an invalid scope, the server will use the given redirect_uri instead of the default c
Replaced deprecated methods with recommended ones when using Lcobucci\JWT\Builder to build a JWT token. (PR #1060)
preg_match() to validate an RSA key, the server will now throw a RuntimeException (PR #1047)Lcobucci\JWT\Builder to build a JWT token. (PR #1060)getIdentifier() added to AccessTokenTrait. The trait cannot be used without the getIdentifier()
method being defined (PR #1051)Flag, requireCodeChallengeForPublicClients, used to reject public clients that do not provide a code challenge for the Auth Code Grant; use AuthCodeGr
requireCodeChallengeForPublicClients, used to reject public clients that do not provide a code challenge for the Auth Code Grant; use AuthCodeGrant::disableRequireCodeCallengeForPublicClients() to turn off this requirement (PR #938)isConfidential getter added to ClientEntity to identify type of client (PR #938)validateClient() added to validate clients which was previously performed by the getClientEntity() function (PR #938)getClientEntityOrFail(). This is a wrapper around the getClientEntity() function that ensures we emit and throw an exception if the repo doesn't return a client entity. (PR #1010)convertToJWT() interface with a more generic __toString() to improve extensibility; AccessTokenEntityInterface now requires setPrivateKey(CryptKey $privateKey) so __toString() has everything it needs to work (PR #874)invalidClient() function accepts a PSR-7 compliant $serverRequest argument to avoid accessing the $_SERVER global variable and improve testing (PR #899)issueAccessToken() in the Abstract Grant no longer sets access token client, user ID or scopes. These values should already have been set when calling getNewToken() (PR #919)enableCodeExchangeProof flag. Any client sending a code challenge will initiate PKCE checks. (PR #938)getClientEntity() no longer performs client validation (PR #938)DateTimeImmutable() instead of DateTime(), time() instead of (new DateTime())->getTimeStamp(), and DateTime::getTimeStamp() instead of DateTime::format('U') (PR #963)enableCodeExchangeProof flag (PR #938)RefreshTokenRepository can now return null, allowing refresh tokens to be optional. (PR #649)
Added error_description to the error payload to improve standards compliance. The contents of this are copied from the existing message value. (PR #10
error_description to the error payload to improve standards compliance. The contents of this are copied from the existing message value. (PR #1006)message value in the next major release (PR #1006)Revert setting keys on response type to be inside getResponseType() function instead of AuthorizationServer constructor (PR #969)
getResponseType() function instead of AuthorizationServer constructor (PR #969)Fix issue with previous release where interface had changed for the AuthorizationServer. Reverted to the previous interface while maintaining function
Moved the finalizeScopes() call from validateAuthorizationRequest method to the completeAuthorizationRequest method so it is called just before the ac
finalizeScopes() call from validateAuthorizationRequest method to the completeAuthorizationRequest method so it is called just before the access token is issued (PR #923)Added newvalidateRedirectUri method AbstractGrant to remove three instances of code duplication (PR #912)
validateRedirectUri method AbstractGrant to remove three instances of code duplication (PR #912)hasRedirect() added to OAuthServerException (PR #703)BadMethodCallException from the verify() method of the JWT token in the validateAuthorization method (PR #904)No longer set a WWW-Authenticate header for invalid clients if the client did not send an Authorization header in the original request (PR #902)
Changed hint for unsupportedGrantType exception so it no longer references the grant type parameter which isn't always expected (PR #893)
Use PHPStan for static analysis of code (PR #848)
- Removed check on empty scopes
Changed the token type issued by the Implicit Grant to be Bearer instead of bearer. (PR #724)
An invalid refresh token that can't be decrypted now returns a HTTP 401 error instead of HTTP 400 (Issue #759)
To address feedback from the security release the following change has been made:
To address feedback from the security release the following change has been made:
Breaking change: The AuthorizationServer constructor now expects an encryption key string instead of a public key
AuthorizationServer constructor now expects an encryption key string instead of a public keyNothing published for this version
Nothing published for this version
Fixed multiple security vulnerabilities as a result of a security audit paid for by the Mozilla Secure Open Source Fund. All users of this library are…
AuthorizationServer instance you set the setEncryptionKey(). This will result in stronger encryption being used. If this method is not set messages will be sent to the defined error handling routines (using error_log). Please see the examples and documentation for examples.Fixed WWW-Authenticate header (Issue #669)
Fixed finalizeScopes call (Issue #650)
finalizeScopes call (Issue #650)Improved test suite (Issue #614)
array_shift with foreach loop (Issue #621)Implemented RFC7636 (Issue #574)
isExpired() method from entity interfaces and traits (Issue #600)paragonie/random_compat 2.x (Issue #606)indigophp/hash-compat to Composer suggestions and require-dev for PHP 5.5 supportFix hints in PasswordGrant (Issue #560)
Resource owner to terminology.md (Issue #561)state parameter is now correctly returned after implicit grant authorization
state parameter is now correctly returned after implicit grant authorizationFixes an issue (#550) whereby it was unclear whether or not to validate a client's secret during a request.
Version 5 is a complete code rewrite.
Version 5 is a complete code rewrite.
Allow multiple client redirect URIs (Issue #511)
Version 5 is a complete code rewrite.
Version 5 is a complete code rewrite.
Your coding agent can read these notes before it upgrades. Set up the MCP server →