Completed
Push — master ( 2afc29...29656f )
by Philip
06:07
created

authenticateToken()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

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