JwsAuthenticator::start()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 2
b 0
f 0
nc 2
nop 2
dl 0
loc 7
rs 10
1
<?php
2
/*
3
 * This file is part of the Guarded Authentication package.
4
 *
5
 * (c) Jafar Jabr <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Jafar\Bundle\GuardedAuthenticationBundle\Guard;
12
13
use Jafar\Bundle\GuardedAuthenticationBundle\Api\ApiResponse\ApiProblem;
14
use Jafar\Bundle\GuardedAuthenticationBundle\Api\ApiResponse\ApiResponseFactory;
15
use Jafar\Bundle\GuardedAuthenticationBundle\Api\JWSEncoder\JWSEncoderInterface;
16
use Jafar\Bundle\GuardedAuthenticationBundle\Api\JWSExtractor\TokenExtractor;
17
use Jafar\Bundle\GuardedAuthenticationBundle\Exception\ApiException;
18
use Symfony\Component\HttpFoundation\Request;
19
use Symfony\Component\Routing\RouterInterface;
20
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
21
use Symfony\Component\Security\Core\Exception\AuthenticationException;
22
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
23
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
24
use Symfony\Component\Security\Core\User\UserInterface;
25
use Symfony\Component\Security\Core\User\UserProviderInterface;
26
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
27
28
/**
29
 * Class JwsAuthenticator.
30
 *
31
 * @author Jafar Jabr <[email protected]>
32
 */
33
class JwsAuthenticator extends AbstractGuardAuthenticator
34
{
35
    /**
36
     * @var JWSEncoderInterface
37
     */
38
    private $jwtEncoder;
39
40
    /**
41
     * @var RouterInterface
42
     */
43
    private $router;
44
45
    /**
46
     * @var ApiResponseFactory
47
     */
48
    private $responseFactory;
49
50
    /**
51
     * @var string
52
     */
53
    private $loginRoute;
54
55
    /**
56
     * JwsAuthenticator constructor.
57
     *
58
     * @param JWSEncoderInterface $jwtEncoder
59
     * @param RouterInterface     $router
60
     * @param ApiResponseFactory  $responseFactory
61
     * @param string              $loginRoute
62
     */
63
    public function __construct(
64
        JWSEncoderInterface $jwtEncoder,
65
        RouterInterface $router,
66
        ApiResponseFactory $responseFactory,
67
        string $loginRoute
68
    ) {
69
        $this->jwtEncoder      = $jwtEncoder;
70
        $this->router          = $router;
71
        $this->responseFactory = $responseFactory;
72
        $this->loginRoute      = $loginRoute;
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78
    public function getCredentials(Request $request)
79
    {
80
        $loginRoute    = $this->loginRoute;
81
        $isLoginSubmit = $request->attributes->get('_route') == $loginRoute && $request->isMethod('POST');
82
        if ($isLoginSubmit) {
83
            return null;
84
        }
85
        $extractor = new TokenExtractor('Bearer', 'Authorization');
86
87
        return $extractor->extract($request) ?? null;
88
    }
89
90
    /**
91
     * {@inheritdoc}
92
     */
93
    public function getUser($credentials, UserProviderInterface $userProvider)
94
    {
95
        try {
96
            $data = $this->jwtEncoder->decode($credentials);
97
        } catch (ApiException $e) {
98
            throw new CustomUserMessageAuthenticationException($e->getMessage());
99
        }
100
101
        $username = $data['username'];
102
103
        return $this->loadUser($userProvider, $username);
104
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109
    public function checkCredentials($credentials, UserInterface $user)
110
    {
111
        return true;
112
    }
113
114
    protected function getLoginUrl()
115
    {
116
        $loginRoute = $this->loginRoute;
117
118
        return $this->router->generate($loginRoute);
119
    }
120
121
    /**
122
     * {@inheritdoc}
123
     */
124
    public function supportsRememberMe()
125
    {
126
        return false;
127
    }
128
129
    /**
130
     * {@inheritdoc}
131
     */
132
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
133
    {
134
        $apiProblem = new ApiProblem(401);
135
        $apiProblem->set('detail', $exception->getMessageKey());
136
137
        return $this->responseFactory->createResponse($apiProblem);
138
    }
139
140
    /**
141
     * {@inheritdoc}
142
     */
143
    public function start(Request $request, AuthenticationException $authException = null)
144
    {
145
        $apiProblem = new ApiProblem(401);
146
        $message    = $authException ? $authException->getMessageKey() : 'Invalid credentials';
147
        $apiProblem->set('detail', $message);
148
149
        return $this->responseFactory->createResponse($apiProblem);
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
156
    {
157
        return null;
158
    }
159
160
    protected function getDefaultSuccessRedirectUrl()
161
    {
162
        return null;
163
    }
164
165
    /**
166
     * {@inheritdoc}
167
     */
168
    public function supports(Request $request)
169
    {
170
        return (bool) $this->getCredentials($request);
171
    }
172
173
    /**
174
     * @param UserProviderInterface $userProvider
175
     * @param string                $username
176
     *
177
     * @return UserInterface
178
     */
179
    private function loadUser(UserProviderInterface $userProvider, string $username)
180
    {
181
        try {
182
            return $userProvider->loadUserByUsername($username);
183
        } catch (UsernameNotFoundException $e) {
184
            throw new CustomUserMessageAuthenticationException($e->getMessage());
185
        }
186
    }
187
}
188