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
Bug
introduced
by
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 |