Passed
Push — master ( 4d963b...5d27b0 )
by Alexander
03:00 queued 01:03
created

src/AutoLoginMiddleware.php (1 issue)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\User;
6
7
use Psr\Http\Message\ResponseInterface;
8
use Psr\Http\Message\ServerRequestInterface;
9
use Psr\Http\Server\MiddlewareInterface;
10
use Psr\Http\Server\RequestHandlerInterface;
11
use Psr\Log\LoggerInterface;
12
use Yiisoft\Auth\IdentityRepositoryInterface;
13
14
/**
15
 * AutoLoginMiddleware automatically logs user in based on cookie.
16
 */
17
final class AutoLoginMiddleware implements MiddlewareInterface
18
{
19
    private User $user;
20
    private IdentityRepositoryInterface $identityRepository;
21
    private LoggerInterface $logger;
22
    private AutoLogin $autoLogin;
23
24 9
    public function __construct(
25
        User $user,
26
        IdentityRepositoryInterface $identityRepository,
27
        LoggerInterface $logger,
28
        AutoLogin $autoLogin
29
    ) {
30 9
        $this->user = $user;
31 9
        $this->identityRepository = $identityRepository;
32 9
        $this->logger = $logger;
33 9
        $this->autoLogin = $autoLogin;
34 9
    }
35
36 9
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
37
    {
38 9
        $this->authenticateUserByCookieFromRequest($request);
39 8
        $guestBeforeHandle = $this->user->isGuest();
40 8
        $response = $handler->handle($request);
41 8
        $guestAfterHandle = $this->user->isGuest();
42
43 8
        if ($guestBeforeHandle && !$guestAfterHandle) {
44 1
            $response = $this->autoLogin->addCookie($this->user->getIdentity(false), $response);
0 ignored issues
show
$this->user->getIdentity(false) of type Yiisoft\User\GuestIdentity is incompatible with the type Yiisoft\User\AutoLoginIdentityInterface expected by parameter $identity of Yiisoft\User\AutoLogin::addCookie(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

44
            $response = $this->autoLogin->addCookie(/** @scrutinizer ignore-type */ $this->user->getIdentity(false), $response);
Loading history...
45
        }
46
47 8
        if (!$guestBeforeHandle && $guestAfterHandle) {
48 1
            $response = $this->autoLogin->expireCookie($response);
49
        }
50
51 8
        return $response;
52
    }
53
54
    /**
55
     * Authenticate user by auto login cookie from request.
56
     *
57
     * @param ServerRequestInterface $request Request instance containing auto login cookie.
58
     */
59 9
    private function authenticateUserByCookieFromRequest(ServerRequestInterface $request): void
60
    {
61 9
        $cookieName = $this->autoLogin->getCookieName();
62 9
        $cookies = $request->getCookieParams();
63
64 9
        if (!array_key_exists($cookieName, $cookies)) {
65 1
            return;
66
        }
67
68
        try {
69 8
            $data = json_decode($cookies[$cookieName], true, 512, JSON_THROW_ON_ERROR);
70 1
        } catch (\Exception $e) {
71 1
            $this->logger->warning('Unable to authenticate user by cookie. Invalid cookie.');
72 1
            return;
73
        }
74
75 7
        if (!is_array($data) || count($data) !== 2) {
76 1
            $this->logger->warning('Unable to authenticate user by cookie. Invalid cookie.');
77 1
            return;
78
        }
79
80 6
        [$id, $key] = $data;
81 6
        $identity = $this->identityRepository->findIdentity($id);
82
83 6
        if ($identity === null) {
84 1
            $this->logger->warning("Unable to authenticate user by cookie. Identity \"$id\" not found.");
85 1
            return;
86
        }
87
88 5
        if (!$identity instanceof AutoLoginIdentityInterface) {
89 1
            throw new \RuntimeException('Identity repository must return an instance of \Yiisoft\User\AutoLoginIdentityInterface in order for auto-login to function.');
90
        }
91
92 4
        if (!$identity->validateAutoLoginKey($key)) {
93 1
            $this->logger->warning('Unable to authenticate user by cookie. Invalid key.');
94 1
            return;
95
        }
96
97 3
        $this->user->login($identity);
98 3
    }
99
}
100