Apr 9, 2026·5 min read·3 visits
Laravel Passport before 13.7.1 allows client credentials tokens to authenticate as real users if client UUIDs are disabled. The TokenGuard incorrectly uses the numeric client identifier as a user ID, leading to full authentication bypass.
An authentication bypass vulnerability in Laravel Passport allows machine-to-machine client credentials tokens to inadvertently authenticate as unrelated users. This occurs due to improper validation of the JWT subject claim when UUIDs are disabled for OAuth clients, resulting in an integer collision between client IDs and user primary keys.
Laravel Passport provides OAuth2 server support for Laravel applications. It relies on the thephpleague/oauth2-server library for core OAuth2 operations. The vulnerability resides in how Passport processes access tokens issued under the client_credentials grant type.
In a client_credentials flow, authentication occurs machine-to-machine. There is no associated user context. The underlying OAuth2 server correctly reflects this by setting the JWT sub (subject) claim to the client identifier because no user identifier is present during token issuance.
Prior to version 13.7.1, Passport's TokenGuard did not validate whether the sub claim represented a user or a client before querying the database. When applications explicitly configured Passport to use integer client IDs, a direct collision between client IDs and user IDs became possible.
The Laravel\Passport\Guards\TokenGuard::authenticateViaBearerToken() method resolves an authenticated user from an incoming Bearer token. It retrieves the oauth_user_id attribute from the parsed PSR-7 request, which corresponds directly to the JWT sub claim.
The method immediately passes this value to the user provider's retrieveById() method. The provider issues a database query to find a user matching the provided integer ID. If the application configuration disables UUIDs for OAuth clients via Passport::$clientUuids = false, both the oauth_clients and users tables share an overlapping integer ID space.
When a machine-to-machine client authenticates, the resulting token contains its numeric client identifier in the sub claim. The TokenGuard extracts this numeric identifier and passes it to the user provider. The application then resolves an actual user account possessing the same numeric primary key.
The vulnerability was patched in version 13.7.1 by modifying the authentication logic within src/Guards/TokenGuard.php. The patch introduces strict validation to ensure that a client_credentials token is not used to falsely authenticate a user session.
Before the patch, the guard simply checked if the oauth_user_id was not empty. It lacked contextual awareness of the grant type used to generate the token. The numeric client ID passed through without scrutiny.
// Vulnerable logic in TokenGuard.php
$oauthUserId = $psr->getAttribute('oauth_user_id');
if (empty($oauthUserId)) {
return null;
}
return $this->provider->retrieveById($oauthUserId);The patched code implements a specific check for the collision scenario. It verifies if the oauth_user_id exactly matches the oauth_client_id and checks whether the token was issued via the client_credentials grant type.
// Patched logic in TokenGuard.php
$oauthUserId = $psr->getAttribute('oauth_user_id');
if (empty($oauthUserId) || ($oauthUserId === $psr->getAttribute('oauth_client_id') && $client->hasGrantType('client_credentials'))) {
return null;
}
return $this->provider->retrieveById($oauthUserId);Exploiting this vulnerability requires the attacker to possess valid client credentials for an application configured with integer client IDs. The target environment must have Passport::$clientUuids explicitly set to false in its configuration.
The attacker begins by authenticating against the OAuth2 token endpoint. They request an access token using the client_credentials grant type, providing their known client ID and client secret.
curl -X POST http://api.example.com/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "client_credentials",
"client_id": "5",
"client_secret": "known-secret"
}'The server responds with a valid JWT access token. The attacker then attaches this token as a Bearer authorization header in a subsequent request directed at an endpoint protected by the auth:api middleware. The application incorrectly authenticates the request as the user whose primary key matches the attacker's client ID.
The vulnerability results in a direct authentication bypass and unauthorized access to user data. An attacker operating a machine-to-machine client gains the ability to impersonate an unrelated user account without requiring the user's credentials.
The exact scope of the impact depends on the privileges associated with the impersonated user account. If the matched user is an administrator, the attacker achieves complete control over the application. The integrity and confidentiality of the victim's data are severely compromised.
The CVSS v3.1 base score is 6.8. The score reflects the network-based attack vector and low privilege requirements. The complexity is rated high because exploitation strictly depends on a non-default configuration (Passport::$clientUuids = false) and the existence of a corresponding numeric user ID.
The primary remediation strategy is upgrading the laravel/passport package to version 13.7.1 or later. The patch effectively neutralizes the vulnerability by explicitly blocking user resolution for client_credentials tokens when the user ID matches the client ID.
If immediate patching is not feasible, administrators should re-enable UUIDs for OAuth clients. This involves setting Passport::$clientUuids = true. Changing this configuration requires migrating existing client records to use UUIDs, which breaks backward compatibility for established integrations.
A secondary mitigation involves disabling the client_credentials grant type if it is not actively utilized. Alternatively, developers can implement custom middleware to inspect incoming requests. The middleware must verify that tokens utilizing the client_credentials grant are restricted from accessing user-specific endpoints.
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
laravel/passport Laravel | < 13.7.1 | 13.7.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-287 |
| Attack Vector | Network |
| CVSS Base Score | 6.8 |
| Impact | Authentication Bypass / Impersonation |
| Exploit Status | Unweaponized / Conditional |
| Required Configuration | Passport::$clientUuids = false |
Software does not properly prove that a user or entity is who they claim to be, leading to an authentication bypass.