Completed
Push — standalone ( 57bbfc...ea253f )
by Philip
03:00
created

AbstractAccessTokenAuthenticator   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 152
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 64.1%

Importance

Changes 0
Metric Value
wmc 18
c 0
b 0
f 0
lcom 1
cbo 8
dl 0
loc 152
ccs 25
cts 39
cp 0.641
rs 10

12 Methods

Rating   Name   Duplication   Size   Complexity  
findUserByToken() 0 1 ?
A authenticateToken() 0 20 3
A supportsToken() 0 4 2
B createToken() 0 21 5
A onAuthenticationFailure() 0 4 1
A getTokenQueryParameterName() 0 4 1
A setTokenQueryParameterName() 0 4 1
A getTokenHeaderName() 0 4 1
A setTokenHeaderName() 0 4 1
A isTokenRequired() 0 4 1
A setTokenRequired() 0 4 1
A createTokenMissingException() 0 4 1
1
<?php
2
3
namespace Dontdrinkandroot\RestBundle\Security;
4
5
use Symfony\Component\HttpFoundation\Request;
6
use Symfony\Component\HttpFoundation\Response;
7
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
8
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
9
use Symfony\Component\Security\Core\Exception\AuthenticationException;
10
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
11
use Symfony\Component\Security\Core\User\UserInterface;
12
use Symfony\Component\Security\Core\User\UserProviderInterface;
13
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
14
use Symfony\Component\Security\Http\Authentication\SimplePreAuthenticatorInterface;
15
16
abstract class AbstractAccessTokenAuthenticator
17
    implements SimplePreAuthenticatorInterface, AuthenticationFailureHandlerInterface
18
{
19
    const DEFAULT_TOKEN_QUERY_PARAMETER_NAME = 'token';
20
    const DEFAULT_TOKEN_HEADER_NAME = 'X-Access-Token';
21
22
    /**
23
     * @var string
24
     */
25
    protected $tokenQueryParameterName = self::DEFAULT_TOKEN_QUERY_PARAMETER_NAME;
26
27
    /**
28
     * @var string
29
     */
30
    protected $tokenHeaderName = self::DEFAULT_TOKEN_HEADER_NAME;
31
32
    /**
33
     * If set to true an AuthenticationException will be thrown if no Access Token was found. Otherwise if will simply
34
     * continue with other authentication methods.
35
     *
36
     * @var bool
37
     */
38
    protected $tokenRequired = false;
39
40
    /**
41
     * {@inheritdoc}
42
     */
43 14
    public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
44
    {
45 14
        $tokenString = $token->getCredentials();
46
47 14
        $user = $this->findUserByToken($tokenString);
48
49 14
        if (null === $user || !$user instanceof UserInterface) {
50
            throw new AuthenticationException('Invalid Access Token');
51
        }
52
53 14
        $userRoles = $user->getRoles();
54 14
        $userRoles[] = 'ROLE_REST_API';
55
56 14
        return new PreAuthenticatedToken(
57
            $user,
58
            $tokenString,
59
            $providerKey,
60
            $userRoles
61
        );
62
    }
63
64
    /**
65
     * {@inheritdoc}
66
     */
67 22
    public function supportsToken(TokenInterface $token, $providerKey)
68
    {
69 22
        return $token instanceof PreAuthenticatedToken && $token->getProviderKey() === $providerKey;
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75 22
    public function createToken(Request $request, $providerKey)
76
    {
77 22
        $token = $request->query->get($this->getTokenQueryParameterName());
78 22
        if (null === $token) {
79 22
            $token = $request->headers->get($this->getTokenHeaderName());
80
        }
81
82 22
        if (null === $token || 'null' === $token) {
83 14
            if ($this->tokenRequired) {
84
                throw $this->createTokenMissingException();
85
            } else {
86 14
                return null;
87
            }
88
        }
89
90 14
        return new PreAuthenticatedToken(
91 14
            'anon.',
92
            $token,
93
            $providerKey
94
        );
95
    }
96
97
    /**
98
     * {@inheritdoc}
99
     */
100
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
101
    {
102
        throw new BadCredentialsException($exception->getMessage(), Response::HTTP_FORBIDDEN, $exception);
103
    }
104
105
    /**
106
     * @return string
107
     */
108 22
    public function getTokenQueryParameterName()
109
    {
110 22
        return $this->tokenQueryParameterName;
111
    }
112
113
    /**
114
     * @param $tokenQueryName
115
     */
116
    public function setTokenQueryParameterName($tokenQueryName)
117
    {
118
        $this->tokenQueryParameterName = $tokenQueryName;
119
    }
120
121
    /**
122
     * @return string
123
     */
124 22
    public function getTokenHeaderName()
125
    {
126 22
        return $this->tokenHeaderName;
127
    }
128
129
    /**
130
     * @param $tokenHeaderName
131
     */
132
    public function setTokenHeaderName($tokenHeaderName)
133
    {
134
        $this->tokenHeaderName = $tokenHeaderName;
135
    }
136
137
    /**
138
     * @return bool
139
     */
140
    public function isTokenRequired()
141
    {
142
        return $this->tokenRequired;
143
    }
144
145
    /**
146
     * @param bool $tokenRequired
147
     */
148 22
    public function setTokenRequired($tokenRequired)
149
    {
150 22
        $this->tokenRequired = $tokenRequired;
151 22
    }
152
153
    /**
154
     * @return AuthenticationException
155
     */
156
    protected function createTokenMissingException()
157
    {
158
        return new BadCredentialsException('No Access Token found');
159
    }
160
161
    /**
162
     * @param $token
163
     *
164
     * @return UserInterface|null
165
     */
166
    protected abstract function findUserByToken($token);
167
}
168