-
Notifications
You must be signed in to change notification settings - Fork 296
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
More granular control over token validation #275
More granular control over token validation #275
Conversation
src/Guard.php
Outdated
$is_valid = $accessToken && ( | ||
($this->expiration && $accessToken->created_at->gt(now()->subMinutes($this->expiration))) | ||
|| $this->hasValidProvider($accessToken->tokenable) | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check doesn't read the same to me. The access token must be not null and then you specify it MUST also have an explicit expiration date. But, I don't think we required tokens to have an expiration date before this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. I tried to inverse the statement to prevent a double negation back to valid
. But in the process I did end up changing the behavior. Was more intent on keeping the tests working. It's fixed now. Hope it makes more sense this way.
Also added an early return on a missing $accessToken
. Because without it we can't deduce a User
so it makes sense to short-circuit there.
@taylorotwell I get that; but it seemed weird to me to create an |
Well even if it was a |
It could be negated and assigned to the protected function isValidAccessToken($accessToken): bool
{
if (! $accessToken) {
return false;
}
$is_valid = ! (
($this->expiration && $accessToken->created_at->lte(now()->subMinutes($this->expiration)))
|| !$this->hasValidProvider($accessToken->tokenable)
);
if (is_callable(Sanctum::$validateCallback)) {
$is_valid = (bool) (Sanctum::$validateCallback)($accessToken, $is_valid);
}
return $is_valid;
} The early In this situation we can:
Otherwise only option 1 is possible. Hope that makes sense. How do you feed about this solution? |
@taylorotwell Sorry for bugging you again on this; but I notices you removed the Say I want to use the normal behavior, but only use the token one time, I now have to re-add the checks to see if the token hasn't expired already. This seems a bit counter productive to me. It can even make the validation less secure, because If iI only implemented a check to see if the token hasn't been used before, I can potentially use a token that has expired long ago. |
@doekenorg best that you send a follow up pr as its unlikely that Taylor will see your reply |
Reason for this feature
Currently Sanctum has a bit of a shotgun approach to validation. You either specify:
There is no easy user control for overwriting this behavior.
By implementing this feature developers are able to make:
Usage
The
Guard
now checks for a validation callback on theSanctum
class. This callback receives:bool
) according to theGuard
To make a single use token you can to this for instance:
Since
Sanctum::$validateCallback
is expected to be a callable, you can replace it with a service from the container if you need to, or make an__invoke()
-able class, or a combination of the two.And because the
Guard
checks if thecallable
is set, this does not cause any breaking changes.Alternative
I first thought about introducing 2 events that could aid in these situations. One to overwrite the validation much like this
callable
is doing. And one after theGuard
validates the token, so some action can be taken to invalidate them; when the business logic is something funky (probably in combination with a customSanctum::$personalAccessTokenModel
setting).But I changed my mind because the feature this PR adds is more
final
as it where. Using events opens the door to other packages that start adding validation logic on top of one another, and I feel like this is something the developer needs to control. Not some behind the scenes magic.It also made more sense to me in the current style of the package. Much like overwriting the
PersonalAccessToken
model on theSanctum
class.