-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
v9 Client Credentials grant broken #1456
Comments
Using "client credentials" grant, the client is the resource owner, so is the subject of the JWT token. |
I can agree with that, but that doesn't make it the user, so maybe the oauth_user_id shouldn't be filled with the sub if the sub is filled with the client id? |
@shades684 Is this issue related to thephpleague/oauth2-server-bundle#191? |
I understand what you mean and it is a naming problem IMO. The We also rely on the new behavior of v9 on Laravel Passport to check whether the token's resource owner is the client itself or not. You may check the situation too like we did and set if ($request->oauth_user_id === $request->oauth_client_id) {
$request->oauth_user_id = null;
} |
@ajgarlag bartholtbos explains the same problem in that issue, but I think he's searching for the solution in the wrong project. @hafezdivandari though i think your solution will work, it feels like we're testing if 2 ids from seperate places are the same. Theoretically they could actually be the same id. @hafezdivandari |
@shades684 you are right, this can't be used if client and user IDs are integers for example. We are using UUID for client IDs on Passport so we are safe. But your point is totally valid.
I agree. It seems wrong to map |
Ok, I finally found the related RFC9068 which is too important to know what the
|
This is a tricky one to resolve. It's correct that the subject should be filled with the client ID when using the client credentials grant as noted by @hafezdivandari. The problem is populating the oauth_user_id field with it when it is clearly not a user ID as it could cause confusion with implementations. I'm not entirely sure what the best way forwards is with this. We could rename the request field to oauth_owner_id or something similar in a later release but if we did this, it would then be correct to assign the sub to this field and I assume you'd still have issues as you want to know when no resource owner is present? Am I understanding that correctly? My gut is telling me we change the name of this in a later release to satisfy when the sub switches between a client ID or resource owner ID and that a modified trait is used in the League Bundle to reinstate the old behaviour for Symfony users in the meantime. |
Adding a custom claim // src/Entities/Traits/AccessTokenTrait.php
private function convertToJWT(): Token
{
// ...
return $this->jwtConfiguration->builder()
// ...
->relatedTo($this->getSubjectIdentifier())
+ ->withClaim('sub_type', $this->getSubjectType())
->getToken($this->jwtConfiguration->signer(), $this->jwtConfiguration->signingKey());
}
+ private function getSubjectType(): string
+ {
+ return is_null($this->getUserIdentifier()) ? 'client' : 'user';
+ }
private function getSubjectIdentifier(): string
{
return $this->getUserIdentifier() ?? $this->getClient()->getIdentifier();
} // src/AuthorizationValidators/BearerTokenValidator.php
public function validateAuthorization(ServerRequestInterface $request): ServerRequestInterface
{
// ...
return $request
->withAttribute('oauth_access_token_id', $claims->get('jti'))
->withAttribute('oauth_client_id', $claims->get('aud')[0])
- ->withAttribute('oauth_user_id', $claims->get('sub'))
+ ->withAttribute('oauth_user_id', $claims->get('sub_type') === 'user' ? $claims->get('sub') : null)
+ ->withAttribute('oauth_owner_id', $claims->get('sub'))
+ ->withAttribute('oauth_owner_type', $claims->get('sub_type'))
->withAttribute('oauth_scopes', $claims->get('scopes'));
} PS: Adding custom claims would be easier after #1328 |
Since version 9 the client credentials grant fills the subject of the jwt token with the client identifier
On line 56 of League\OAuth2\Server\Grant\ClientCredentialsGrant the userIdentifier is set to null
On line 107 of League\OAuth2\Server\Entities\Traits\AccessTokenTrait the SubjectIdentifier is therefor filled with de identifier of the client
When using the given jwt token:
On line 132 of League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator the oauth_user_id is set to the value of sub (which is the subject identifier mentioned above)
The definition of sub says:
This value if used in
Line 91 of League\Bundle\OAuth2ServerBundle\Security\Authenticator checks if sub should return a NullUser if we don't have a user, but now it doesn't and we get an error.
I expect the SubjectIdentifier of the AccessTokenTrait should be nullable and not return the client id in the subject if we have no user.
I don't know if this has been done intentionally or my assumptions are correct.
The text was updated successfully, but these errors were encountered: