getLastAuthenticationError()   B
last analyzed

Complexity

Conditions 6
Paths 8

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 8.8337
c 0
b 0
f 0
cc 6
nc 8
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Explicit Architecture POC,
7
 * which is created on top of the Symfony Demo application.
8
 *
9
 * (c) Herberto Graça <[email protected]>
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
namespace Acme\App\Infrastructure\Auth\Authentication;
16
17
use Acme\App\Core\Component\User\Application\Repository\UserRepositoryInterface;
18
use Acme\App\Core\Component\User\Domain\User\User;
19
use Acme\App\Core\Port\Auth\Authentication\AuthenticationException;
20
use Acme\App\Core\Port\Auth\Authentication\AuthenticationServiceInterface;
21
use Acme\App\Core\Port\Auth\Authentication\NoUserAuthenticatedException;
22
use Acme\App\Core\SharedKernel\Component\User\Domain\User\UserId;
23
use Psr\Http\Message\ServerRequestInterface;
24
use Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface;
25
use Symfony\Component\HttpFoundation\Session\SessionInterface;
26
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
27
use Symfony\Component\Security\Core\Exception\AuthenticationException as SymfonyAuthenticationException;
28
use Symfony\Component\Security\Core\Security;
29
use Symfony\Component\Security\Csrf\CsrfToken;
30
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
31
32
final class AuthenticationService implements AuthenticationServiceInterface
33
{
34
    /**
35
     * @var CsrfTokenManagerInterface
36
     */
37
    private $csrfTokenManager;
38
39
    /**
40
     * @var TokenStorageInterface
41
     */
42
    private $tokenStorage;
43
44
    /**
45
     * @var HttpFoundationFactoryInterface
46
     */
47
    private $symfonyRequestFactory;
48
49
    /**
50
     * @var SessionInterface
51
     */
52
    private $session;
53
54
    /**
55
     * @var UserRepositoryInterface
56
     */
57
    private $userRepository;
58
59
    public function __construct(
60
        CsrfTokenManagerInterface $csrfTokenManager,
61
        TokenStorageInterface $tokenStorage,
62
        HttpFoundationFactoryInterface $symfonyRequestFactory,
63
        SessionInterface $session,
64
        UserRepositoryInterface $userRepository
65
    ) {
66
        $this->csrfTokenManager = $csrfTokenManager;
67
        $this->tokenStorage = $tokenStorage;
68
        $this->symfonyRequestFactory = $symfonyRequestFactory;
69
        $this->session = $session;
70
        $this->userRepository = $userRepository;
71
    }
72
73
    public function isCsrfTokenValid(string $id, string $token): bool
74
    {
75
        return $this->csrfTokenManager->isTokenValid(new CsrfToken($id, $token));
76
    }
77
78
    public function getLoggedInUserId(): UserId
79
    {
80
        return $this->getSecurityUser()->getUserId();
81
    }
82
83
    public function getLoggedInUser(): User
84
    {
85
        return $this->userRepository->findOneById($this->getLoggedInUserId());
86
    }
87
88
    public function getLastAuthenticationError(
89
        ServerRequestInterface $request,
90
        bool $clearSession = true
91
    ): ?AuthenticationException {
92
        $request = $this->symfonyRequestFactory->createRequest($request);
93
        $session = $this->session;
94
        /** @var SymfonyAuthenticationException|null $symfonyAuthenticationException */
95
        $symfonyAuthenticationException = null;
96
97
        if ($request->attributes->has(Security::AUTHENTICATION_ERROR)) {
98
            $symfonyAuthenticationException = $request->attributes->get(Security::AUTHENTICATION_ERROR);
99
        } elseif ($session !== null && $session->has(Security::AUTHENTICATION_ERROR)) {
100
            $symfonyAuthenticationException = $session->get(Security::AUTHENTICATION_ERROR);
101
102
            if ($clearSession) {
103
                $session->remove(Security::AUTHENTICATION_ERROR);
104
            }
105
        }
106
107
        return $symfonyAuthenticationException
108
            ? new AuthenticationException(
109
                $symfonyAuthenticationException->getMessage(),
110
                $symfonyAuthenticationException->getCode(),
111
                $symfonyAuthenticationException,
112
                $symfonyAuthenticationException->getMessageKey(),
113
                $symfonyAuthenticationException->getMessageData()
114
            )
115
            : null;
116
    }
117
118
    public function getLastAuthenticationUsername(ServerRequestInterface $request): string
119
    {
120
        $request = $this->symfonyRequestFactory->createRequest($request);
121
        if ($request->attributes->has(Security::LAST_USERNAME)) {
122
            return $request->attributes->get(Security::LAST_USERNAME, '');
123
        }
124
125
        return $this->session === null ? '' : $this->session->get(Security::LAST_USERNAME, '');
126
    }
127
128
    private function getSecurityUser(): SecurityUser
129
    {
130
        $token = $this->tokenStorage->getToken();
131
132
        if ($token === null) {
133
            throw new NoUserAuthenticatedException();
134
        }
135
136
        $securityUser = $token->getUser();
137
        if (!$securityUser instanceof SecurityUser) {
138
            throw new NoUserAuthenticatedException();
139
        }
140
141
        return $securityUser;
142
    }
143
}
144