The package handles user-related functionality:
- Login and logout.
- Getting currently logged in identity.
- Changing current identity.
- Access checking for current user.
- Auto login based on identity from request attribute.
- Auto login or "remember me" based on request cookie.
- PHP 8.1 or higher.
JSON
PHP extension.
The package could be installed with Composer:
composer require yiisoft/user
This package is an addition to yiisoft/auth and provides additional functionality for interacting with user identity.
The CurrentUser
class is responsible for login and logout, as well as for providing data about the current user identity.
/**
* @var \Psr\EventDispatcher\EventDispatcherInterface $eventDispatcher
* @var \Yiisoft\Auth\IdentityRepositoryInterface $identityRepository
*/
$currentUser = new \Yiisoft\User\CurrentUser($identityRepository, $eventDispatcher);
If the user has not been logged in, then the current user is a guest:
$currentUser->getIdentity(); // \Yiisoft\User\Guest\GuestIdentity instance
$currentUser->getId(); // null
$currentUser->isGuest(); // bool
If you need to use a custom identity class to represent guest user, you should pass an instance
of GuestIdentityFactoryInterface
as a third optional parameter when creating CurrentUser
:
/**
* @var \Psr\EventDispatcher\EventDispatcherInterface $eventDispatcher
* @var \Yiisoft\Auth\IdentityRepositoryInterface $identityRepository
* @var \Yiisoft\User\Guest\GuestIdentityFactoryInterface $guestIdentityFactory
*/
$currentUser = new \Yiisoft\User\CurrentUser($identityRepository, $eventDispatcher, $guestIdentityFactory);
Also, you can override an identity instance in runtime:
/**
* @var \Yiisoft\Auth\IdentityInterface $identity
*/
$currentUser->getIdentity(); // Original identity instance
$currentUser->overrideIdentity($identity);
$currentUser->getIdentity(); // Override identity instance
$currentUser->clearIdentityOverride();
$currentUser->getIdentity(); // Original identity instance
It can be useful to allow admin or developer to validate another user's problems.
There are two methods for login and logout:
/**
* @var \Yiisoft\Auth\IdentityInterface $identity
*/
$currentUser->getIdentity(); // GuestIdentityInterface instance
if ($currentUser->login($identity)) {
$currentUser->getIdentity(); // $identity
// Some actions
}
if ($currentUser->logout()) {
$currentUser->getIdentity(); // GuestIdentityInterface instance
// Some actions
}
Both methods trigger events. Events are of the following classes:
Yiisoft\User\Event\BeforeLogin
- triggered at the beginning of login process. Listeners of this event may call$event->invalidate()
to cancel the login process.Yiisoft\User\Event\AfterLogin
- triggered at the ending of login process.Yiisoft\User\Event\BeforeLogout
- triggered at the beginning of logout process. Listeners of this event may call$event->invalidate()
to cancel the logout process.Yiisoft\User\Event\AfterLogout
- triggered at the ending of logout process.
Listeners of these events can get an identity instance participating in the process using $event->getIdentity()
.
Events are dispatched by Psr\EventDispatcher\EventDispatcherInterface
instance, which is specified in the
constructor when the Yiisoft\User\CurrentUser
instance is initialized.
To be able to check whether the current user can perform an operation corresponding to a given permission, you need to set an access checker (see yiisoft/access) instance:
/**
* @var \Yiisoft\Access\AccessCheckerInterface $accessChecker
*/
$currentUser = $currentUser->withAccessChecker($accessChecker);
To perform the check, use can()
method:
// The name of the permission (e.g. "edit post") that needs access check.
$permissionName = 'edit-post'; // Required.
// Name-value pairs that would be passed to the rules associated with the roles and permissions assigned to the user.
$params = ['postId' => 42]; // Optional. Default is empty array.
if ($currentUser->can($permissionName, $params)) {
// Some actions
}
Note that in case access checker is not provided via withAccessChecker()
method, can()
will always return false
.
The current user can store user ID and authentication timeouts for auto-login in the session. To do this, you need to provide a session (see yiisoft/session) instance:
/**
* @var \Yiisoft\Session\SessionInterface $session
*/
$currentUser = $currentUser->withSession($session);
You can set timeout (number of seconds), during which the user will be logged out automatically in case of remaining inactive:
$currentUser = $currentUser->withAuthTimeout(3600);
Also, an absolute timeout (number of seconds) could be used. The user will be logged out automatically regardless of activity:
$currentUser = $currentUser->withAbsoluteAuthTimeout(3600);
By default, timeouts are not used, so the user will be logged out after the current session expires.
The Yiisoft\User\CurrentUser
instance is stateful, so when you build long-running applications
with tools like Swoole or RoadRunner you should reset
the state at every request. For this purpose, you can use the clear()
method.
For auto login, you can use the Yiisoft\User\Login\LoginMiddleware
. This middleware automatically logs user
in if Yiisoft\Auth\IdentityInterface
instance presents in a request attribute. It is usually put there by
Yiisoft\Auth\Middleware\Authentication
. For more information about the authentication middleware and
authentication methods, see the yiisoft/auth.
Please note that
Yiisoft\Auth\Middleware\Authentication
should be located beforeYiisoft\User\Login\LoginMiddleware
in the middleware stack.
In order to log user in automatically based on request cookie presence,
use Yiisoft\User\Login\Cookie\CookieLoginMiddleware
.
To use a middleware, you need to implement Yiisoft\User\Login\Cookie\CookieLoginIdentityInterface
and also implement and use an instance of IdentityRepositoryInterface
in the CurrentUser
,
which will return CookieLoginIdentityInterface
:
use App\CookieLoginIdentity;
use Yiisoft\Auth\IdentityRepositoryInterface;
final class CookieLoginIdentityRepository implements IdentityRepositoryInterface
{
private Storage $storage;
public function __construct(Storage $storage)
{
$this->storage = $storage;
}
public function findIdentity(string $id): ?Identity
{
return new CookieLoginIdentity($this->storage->findOne($id));
}
}
The CookieLoginMiddleware
will check for the existence of a cookie in the request,
validate it and login the user automatically.
By default, you should set cookie for auto login manually in your application after logging user in:
public function login(
\Psr\Http\Message\ServerRequestInterface $request,
\Psr\Http\Message\ResponseFactoryInterface $responseFactory,
\Yiisoft\User\Login\Cookie\CookieLogin $cookieLogin,
\Yiisoft\User\CurrentUser $currentUser
): \Psr\Http\Message\ResponseInterface {
$response = $responseFactory->createResponse();
$body = $request->getParsedBody();
// Get user identity based on body content.
/** @var \Yiisoft\User\Login\Cookie\CookieLoginIdentityInterface $identity */
if ($currentUser->login($identity) && ($body['rememberMe'] ?? false)) {
$response = $cookieLogin->addCookie($identity, $response);
}
return $response;
}
In the above rememberMe
in the request body may come from a "remember me" checkbox in the form. End user decides
if he wants to be logged in automatically. If you do not need the user to be able to choose and want to always use
"remember me", you can enable it via the forceAddCookie
in params.php
:
return [
'yiisoft/user' => [
'authUrl' => '/login',
'cookieLogin' => [
'forceAddCookie' => true,
'duration' => 'P5D', // 5 days
],
],
];
If you want the cookie to be a session cookie, change the duration to
null
.
The Yiisoft\User\Login\Cookie\CookieLoginMiddleware
automatically removes the cookie after the logout.
But you can also remove the cookie manually:
public function logout(
\Psr\Http\Message\ResponseFactoryInterface $responseFactory,
\Yiisoft\User\Login\Cookie\CookieLogin $cookieLogin,
\Yiisoft\User\CurrentUser $currentUser
): \Psr\Http\Message\ResponseInterface {
$response = $responseFactory
->createResponse(302)
->withHeader('Location', '/');
// Regenerate cookie login key to `Yiisoft\User\Login\Cookie\CookieLoginIdentityInterface` instance.
if ($currentUser->logout()) {
$response = $cookieLogin->expireCookie($response);
}
return $response;
}
The login cookie value is stored raw. To prevent the substitution of the cookie value,
you can use a Yiisoft\Cookies\CookieMiddleware
. For more information, see
Yii guide to cookies.
Please note that
Yiisoft\Cookies\CookieMiddleware
should be located beforeYiisoft\User\Login\Cookie\CookieLoginMiddleware
in the middleware stack.
You can find examples of the above features in the yiisoft/demo.
If you need help or have a question, the Yii Forum is a good place for that. You may also check out other Yii Community Resources.
The Yii User is free software. It is released under the terms of the BSD License.
Please see LICENSE
for more information.
Maintained by Yii Software.