Hey! everyone!
I am getting error in cakephp 5 with authentication plugin
Fatal error: Declaration of App\Model\Entity\User::applyScope($action, $resource) must be compatible with Authorization\IdentityInterface::applyScope(string $action, mixed $resource, mixed …$optionalArgs): mixed in /var/www/html/evo/src/Model/Entity/User.php on line 123
please help me
adjust your methods to the new method signature as the error says
See authorization/src/IdentityDecorator.php at 3.x · cakephp/authorization · GitHub on how it should look like
I am also confused why you need applyScope
on a User entity…
hehhehehe… actually i have different ID column in users table…>
public function getIdentifier()
{
return $this->reffer_id;
}
so because this(reffer_id) i have to define all that methods into user entity… if you any suggestion please kindly guide me @KevinPfeifer and please demo code… for adjust your methods to the new method signature as the error says(any example).
Thats why I gave you the link from above but let me just copy paste the code in here
public function applyScope(string $action, mixed $resource, mixed ...$optionalArgs): mixed
{
return $this->authorization->applyScope($this, $action, $resource, ...$optionalArgs);
}
you will also need to adjust this
public function getOriginalData(): \ArrayAccess|array
{
return $this;
}
because as you can see CakePHP 5 has added parameter as well as return types.
And object oriented PHP requires overwritten methods (which you have here) to be defined the same as they are in their parents/interfaces.
What I want to say with this is the fact, that this is not a CakePHP specific error but a general PHP error which you should learn to understand and fix yourself in the future because they may come up more often.
I can’t tell you if your system is acutally good or not, it just feels weird to me
Also the authorization plugin provides a Identity Decorator for stuff like that as you can see here:
https://book.cakephp.org/authorization/3/en/checking-authorization.html
You then don’t need to implement what you do
Ah! I got it @KevinPfeifer thanks. It means that I can do same things from the policies and can validate what should guest can access… Am I right?
policies as well as scopes get the currently logged in user passed in. See my workshop video
But getIdentifier not working in policies… because I want to replace the Id… with refer_id, it is not working in Entity policy or Table Policy.
public function getIdentifier()
{
return $this->refer_id;
}
Ok…sure i will check @KevinPfeifer
it return null now…hehhehhehe
well how did you set the authorization service in the entity previously if this worked in cake4
I just checked the docs. Make sure you have this inside your entity as well
public function setAuthorization(AuthorizationServiceInterface $service)
{
$this->authorization = $service;
return $this;
}
The docs in Authorization Middleware - 3.x need to be updated so they are not 100% correct
yeah cakephp 4 work perfectly but in cakephp 5 raise error at this step
> <?php
>
> declare(strict_types=1);
>
> namespace App\Model\Entity;
>
> use Cake\ORM\Entity;
>
> use Authentication\PasswordHasher\DefaultPasswordHasher;
> use Authorization\IdentityInterface as AuthorizationIdentity;
> use Authentication\IdentityInterface as AuthenticationIdentity;
> use Authorization\AuthorizationServiceInterface;
> use Authorization\IdentityInterface;
> use Authorization\Policy\ResultInterface;
>
> /**
> * User Entity
> *
> * @property int $id
> * @property string|null $username
> * @property string|null $email
> * @property string|null $password
> * @property string|null $token
> * @property \Cake\I18n\DateTime|null $token_expire
> * @property \Cake\I18n\DateTime|null $token_expiration
> * @property int|null $userkeyid
> * @property string|null $api_token
> * @property \Cake\I18n\DateTime|null $activation_date
> * @property float|null $longitude
> * @property float|null $latitude
> * @property int|null $active
> * @property \Cake\I18n\DateTime|null $tos_date
> * @property string|null $secret
> * @property int|null $secret_verified
> * @property string|null $account_verify
> * @property int|null $is_superuser
> * @property int|null $role_id
> * @property \Cake\I18n\Date|null $join_date
> * @property \Cake\I18n\DateTime|null $login_time
> * @property \Cake\I18n\DateTime|null $logout_time
> * @property \Cake\I18n\DateTime|null $created
> * @property \Cake\I18n\DateTime|null $modified
> * @property \Cake\I18n\DateTime|null $trashed
> *
> * @property \App\Model\Entity\Role[] $roles
> * @property \App\Model\Entity\Profile[] $profiles
> */
> class User extends Entity implements AuthorizationIdentity, AuthenticationIdentity
> {
> /**
> * Fields that can be mass assigned using newEntity() or patchEntity().
> *
> * Note that when '*' is set to true, this allows all unspecified fields to
> * be mass assigned. For security purposes, it is advised to set '*' to false
> * (or remove it), and explicitly make individual fields accessible as needed.
> *
> * @var array<string, bool>
> */
> protected array $_accessible = [
> 'username' => true,
> 'email' => true,
> 'password' => true,
> 'token' => true,
> 'token_expire' => true,
> 'token_expiration' => true,
> 'refer_id' => true,
> 'api_token' => true,
> 'activation_date' => true,
> 'longitude' => true,
> 'latitude' => true,
> 'active' => true,
> 'tos_date' => true,
> 'secret' => true,
> 'secret_verified' => true,
> 'account_verify' => true,
> 'is_superuser' => true,
> 'role_id' => true,
> 'join_date' => true,
> 'login_time' => true,
> 'logout_time' => true,
> 'created' => true,
> 'modified' => true,
> 'trashed' => true,
> 'roles' => true,
> 'profile' => true,
> ];
>
> /**
> * Fields that are excluded from JSON versions of the entity.
> *
> * @var array<string>
> */
> protected array $_hidden = [
> 'password',
> 'token',
> ];
>
> protected function _setPassword(string $password)
> {
> $hasher = new DefaultPasswordHasher();
> return $hasher->hash($password);
> }
>
> /**
> * Authorization\IdentityInterface method
> */
> public function can($action, $resource): bool
> {
> return $this->authorization->can($this, $action, $resource);
> }
>
> /**
> * Authorization\IdentityInterface method
> */
> public function canResult($action, $resource): ResultInterface
> {
> return $this->authorization->canResult($this, $action, $resource);
> }
>
> /**
> * Authorization\IdentityInterface method
> */
> public function applyScope(string $action, mixed $resource, mixed ...$optionalArgs): mixed
> {
> return $this->authorization->applyScope($this, $action, $resource, ...$optionalArgs);
> }
>
> /**
> * Authorization\IdentityInterface method
> */
> public function getOriginalData(): \ArrayAccess|array
> {
> return $this;
> }
>
> /**
> * Setter to be used by the middleware.
> */
> public function setAuthorization(AuthorizationServiceInterface $service)
> {
> $this->authorization = $service;
>
> return $this;
> }
>
> public function getIdentifier(): int
> {
> return $this->refer_id;
> }
> }
Well that is fine but did you also follow the docs to add
$middlewareQueue->add(new AuthorizationMiddleware($this, [
'identityDecorator' => function ($auth, $user) {
return $user->setAuthorization($auth);
}
]));
in your middlewarequeue?
already define @KevinPfeifer but yes its work now thanks a lot @KevinPfeifer
->add(new AuthorizationMiddleware($this, [
'unauthorizedHandler' => [
'className' => 'Authorization.Redirect',
'url' => '/accounts/login',
'queryParam' => 'redirectUrl',
'exceptions' => [
MissingIdentityException::class,
ForbiddenException::class
],
],
'identityDecorator' => function ($auth, $user) {
return $user->setAuthorization($auth);
}
]))
the docs will soon be updated. Happy that it works now
yes! docs must be updated and thank to help me @KevinPfeifer cakephp is best framework
Thanks for the nice words but there are always things to improve
1 Like