-
Notifications
You must be signed in to change notification settings - Fork 780
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
Client credentials middleware should allow any sort of valid/existing client #1125
Comments
Just to add up to this issue, it should be either a Personal Access Client or Password Grant Client to replicate the Unauthorized response and not simply a Client Credentials Grant. |
Thanks. I fixed that now to get it more clear. |
I'll need @Sephster & @alshf89 to both weigh in here. Even @matt-allan if you're willing to. We need to get a consensus about this once and for all so that we don't go back and forth changing things all the time. |
@billriess @soundsgoodsofar would be cool if you both could also give your insights here given your involvement on the original issue here: #691 |
In our apis we use both password and client_credentials grants using the same oauth client. We require the consumer apps to use client credentials for non-user apis like pulling app configuration or registering new users then password grants for authenticating. All of our apps are first party though so we can trust this use case. While I agree that the middleware should work for all grant types, this would be an unexpected flow for our use case. If this is changed it would likely need a major version bump to prevent breaking existing use cases. |
Has some one got a workaround going for this, while it will or not will be changed? |
@T0miii don't upgrade to 8.0 for now |
I am not so sure to understand your issue here. If a token is obtained using the client credentials grant, it will be allowed to pass ONLY through the routes protected by the CheckClientCredentials middleware. A token issued using client credentials grant does not pass through a route protected by auth:api. Only the tokens that have a user associated with it can pass the auth:api middleware (those are the ones using password, or authorization code, or even personal, grants). Now, finally, I think this is not a matter of a consensus but more of following the OAuth2 directives. Here is the official RFC for the client credentials grant in the OAuth2 specification: 4.4. Client Credentials Grant. As in the previous RFC there is no distinction of the "client type" at all, it only matters if the credentials are correct or not to get an access token. Once again, as the standard says, this grant is intended to provide access to ANY route which is not related to any user recourse (which is the current way to work of Laravel Passport). It seems like we are accommodating Passport to the use cases of some, instead of stick to the specification itself. |
I agree that the middleware should only care about authenticating the client, for any grant type. The issue for our implementation is the opposite of what you described. In our case, we don't want the Again, just to be clear, I agree with your original post. The middleware should only care about validating the client, not the grant type. |
OK, I think I understand now. So, I think this should be resolved, of course, at app level and not in the package as currently seems to be. Just to provide a possible solution to your case, you can add one middleware or condition checking the client type and blocking access the case it is not the client type you want (basically the same segment is currently causing the issues here). I think we agree on the issue about the current way it is working, so if @driesvints is OK with it, I would send a PR to remove the current behavior. Additionally, I would like to know if it will require a major release again or just a fix on the current one? |
as long as I remember, I faced with this issue when I had some API routes that didn't belong to User scope API but |
OK, I get your point, but the implementation is not correct, so. As it is restricting the client and not the token itself. ANY client can issue a token using client_credentials grant type, so you should not restrict based on the client type but in the grant used to obtain that specific token (following your idea). Now, in the RFC, there is not any detail about this, so even when your point is valid (about restricting this only to access tokens obtained using the client_credentials grant) there is not a specification that says if any other access token still valid or not. From the logic, even when a client used the password grant to obtain an access token, its credentials still being valid, so that client (using that token) can definitively pass through the client.credentials middleware as well. The main purpose of the client.credentials middleware is to validate the credentials of the clients, which, by definition, are correct if the access token is valid. Finally, I am not basing this in my thinking of how should it work, it is based on the current implementations and RFCs. Even when the client_credentials grant is suitable to issue tokens for machine-to-machine communication is not the only case of use. Those access tokens are valid for any case where "the client making the requests don’t require a user’s permission" (REF1, REF2). I hope it helps to resolve the current issue. Again, if @driesvints or anyone behind this is OK I would make a PR to remove that small segment in the condition verifying the client type, which is completely wrong (even for the use case mentioned by @alshf89). Please let me know, I would like to resolve this as soon as possible as it is probably affecting a lot of projects. |
Hey @driesvints sorry for the late response. I don't think the check is required. Apologies for the wall of text as you will no doubt be aware of all that I'm writing. I've mainly laid it out to get my thoughts down. The middleware is called The
Similarly, I don't think we need to check if there is a token in the DB. The only reason I can think to do this is to find out if the token is revoked but we already have a method that does this in the token repository so there is no reason to keep this method. It doesn't serve a purpose as far as I can see. The next method in the Upon initial review we had come to the conclusion that it was best to keep this method for personal access tokens where you can edit the scopes of the token without reissuing the personal access token. I looked into this and I think the way that the personal access token is created at the moment won't allow for this. It is a signed JWT like all the other access tokens meaning it can't be tampered with. There is no need to check these against the DB as we can be sure that if the access token passes validation in the OAuth2-Server, the scopes are the ones that were approved in the original access request. Unfortunately the only way to edit these is to issue a new token as any modification will result in an auth fail. In summary, I think the |
I very agree with everything. Anyway, our main purpose (at least for this issue) is to remove the client type verification (the call to Now, even when it seems to be a breaking change, it is basically a fix to return Passport to the regular and accurate behavior. Of course, it is a decision from the maintainers if put it as a fix or bump the version and consider this a breaking change. So, once again, if @driesvints can let me know, I will gladly make the PR but need to know if do this to the current version or the upcoming one. Anyway, I think, even when it would be for a future version, that version should be released almost immediately. Let me know guys, I am just waiting for the green light :) Thanks :) |
Can you list the exact changes you'd like to make? Then we can determine if it can go to 6.x or master. |
This is literally a small segment. In this line the condition would change from I would need to check locally if there is any test involved on this which could need any change as well. So even when it is a minor fix, it changes the current behavior, but still being a fix introduced after release or version 8.0. So, that's all. Let me know how it sounds to you. |
We have same structure... |
Yes, following those possibilities, even when that was not the correct way to go, that would be a breaking change for some projects so probably need to be in a major release. |
@billriess @alshf89 do you both agree that the change mentioned here is the correct one and that we should implement it? |
In my opinion I’m sort of agree with @JuanDMeGon, but this issue (#691) was really important for lots of people and one of them was me and talked about it a lot so we have decided about it and have created a PR and fix it on that moment. Everyone have different use cases for this scenario so we should find the best practices and best approach for this section, @JuanDMeGon did some research about it and he said its not correct and we should not filter token base on client type but like he said :
And beside @Sephster’s explanation which is very great in detail, he said, we don’t need them (those changes) at all... But I think we should talk about it more to find out how many developers or projects will imapct these changes or why does issue #691 created in first place? or why does PRs accept on it ? We used laravel/passport in lots of project like @billriess mentioned, in some of them we faced this issue and we talked about it ... but on that moment these changes didn’t exist in laravel/passport package so we extended those middlewares and override the validate methods based on what we needed in our projects. If we can issue an access token via client credential grant type for password credential client then I think it is fine like @JuanDMeGon said So @driesvints, changes on this section is up to laravel/passport community and what u guys decide and what is the best approach... |
I understand the use-cases exposed. I think the solution proposed was functional BUT not correct, especially at the package level. |
I like the idea of |
I think @JuanDMeGon has hit the nail on the head. There was a misunderstanding of the middleware in #691. If people want to restrict certain grants this should be a userland issue and not a Passport implementation. This is not something the OAuth spec deals with (nor should it). Effectively, it is the scopes that typically restrict what actions you can do with an access token, not the client type. Using the client type in this manner is something custom and niche. I fell that both the verify functions should be stripped out in their current form. It probably is a major change though as some people have already pointed out they rely on this functionality. |
Very agree. So, I think I would make the PR to the next major release. Anyway, I think this release should be released as soon as possible to return Passport to its regular/correct behavior. I will wait a few, in case @driesvints or someone else has something to add, and then will send a small PR with the fix. Thank you all for the comments. I am glad we get into a solution. |
We only just released a new major version so we probably won't be releasing a new one anytime soon. If this gets merged on master you could use Feel free to send in a PR to master. |
Ok, I understand that. I hope there does not pass so much time on it. |
[9.x] Client credentials middleware should allow any valid client (#1125)
We merged this into master. Thanks for everyone's participation in figuring this out! |
@driesvints I'm a bit stuck here, why the merge is in the master branch since December and not inside the latest release 8.4.1? Bests |
@sylouuu this will be released in the next major version (Passport 9), will be probably around the release of Laravel 7. |
Last december a change was made to allow any valid client : Based on the theory and official standards of OAuth2: "The Client Credentials grant is used when applications request an access token to access their own resources, not on behalf of a user." (REF1, REF2). Shouldn't this change be persistant ? (taylorotwell merged commit on 5 Dec 2019) Ref laravel#1125 laravel#1132
Description:
Currently, it is not possible to get access to any action protected by the ClientCredentials middleware (CheckClientCredentials) if using a password or a personal client. BUT it should be possible, as those clients still being valid clients.
Now, even when it was discussed and seems to be a lot of confusion about this. The only job for the CheckClientCredentials middleware is to validate if the client is a valid client; does not matter the type of client it is.
Based on the theory and official standards of OAuth2: "The Client Credentials grant is used when applications request an access token to access their own resources, not on behalf of a user." (REF1, REF2). So, basically you use the CheckClientCredentials to protect the route and validate if the request comes from a valid client (independently of the type of client). In fact, a token obtained using the client credentials grant does not have a user associated with it, so any user-related action is going to fail.
It was introduced in #1040 with the call to
$token->client->firstParty()
(source).In conclusion: If ANY client obtains an access token using the client credentials grant it SHOULD be authorized when making a request to an endpoint protected with the CheckClientCredentials middleware and currently it is not working that way.
Steps To Reproduce:
Thanks in advance. I hope it helps to resolve the current issues with this.
The text was updated successfully, but these errors were encountered: