Passed
Push — master ( 485653...13929a )
by Florian
06:42
created

TokenAuthenticator   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 166
Duplicated Lines 0 %

Test Coverage

Coverage 97.5%

Importance

Changes 0
Metric Value
wmc 17
eloc 35
dl 0
loc 166
ccs 39
cts 40
cp 0.975
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A setTokenPrefix() 0 5 1
A authenticate() 0 16 3
A getTokenFromQuery() 0 9 2
A setHeaderName() 0 5 1
A getToken() 0 13 4
A unauthorizedChallenge() 0 2 1
A getTokenFromHeader() 0 10 3
A stripTokenPrefix() 0 3 1
A setQueryParam() 0 5 1
1
<?php
2
declare(strict_types=1);
3
/**
4
 * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
5
 * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
6
 *
7
 * Licensed under The MIT License
8
 * For full copyright and license information, please see the LICENSE.txt
9
 * Redistributions of files must retain the above copyright notice.
10
 *
11
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
12
 * @link          https://cakephp.org CakePHP(tm) Project
13
 * @since         1.0.0
14
 * @license       https://opensource.org/licenses/mit-license.php MIT License
15
 */
16
namespace Phauthentic\Authentication\Authenticator;
17
18
use Phauthentic\Authentication\Identifier\IdentifierInterface;
19
use Psr\Http\Message\ServerRequestInterface;
20
21
/**
22
 * Token Authenticator
23
 *
24
 * Authenticates an identity based on a token in a query param or the header.
25
 */
26
class TokenAuthenticator extends AbstractAuthenticator implements StatelessInterface
27
{
28
    /**
29
     * Query param
30
     *
31
     * @var null|string
32
     */
33
    protected $queryParam = null;
34
35
    /**
36
     * Header
37
     *
38
     * @var null|string
39
     */
40
    protected $header = null;
41
42
    /**
43
     * Token Prefix
44
     *
45
     * @var null|string
46
     */
47
    protected $tokenPrefix = null;
48
49
    /**
50
     * Sets the header name to get the token from
51
     *
52
     * @param null|string $name Name
53
     * @return $this
54
     */
55 6
    public function setHeaderName(?string $name): self
56
    {
57 6
        $this->header = $name;
58
59 6
        return $this;
60
    }
61
62
    /**
63
     * Sets the query param to get the token from
64
     *
65
     * @param null|string $queryParam Query param
66
     * @return $this
67
     */
68 6
    public function setQueryParam(?string $queryParam): self
69
    {
70 6
        $this->queryParam = $queryParam;
71
72 6
        return $this;
73
    }
74
75
    /**
76
     * Sets the token prefix
77
     *
78
     * @param null|string $prefix Token prefix
79
     * @return $this
80
     */
81 3
    public function setTokenPrefix(?string $prefix): self
82
    {
83 3
        $this->tokenPrefix = $prefix;
84
85 3
        return $this;
86
    }
87
88
    /**
89
     * Checks if the token is in the headers or a request parameter
90
     *
91
     * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information.
92
     * @return string|null
93
     */
94 24
    protected function getToken(ServerRequestInterface $request): ?string
95
    {
96 24
        $token = $this->getTokenFromHeader($request, $this->header);
97 24
        if ($token === null) {
98 18
            $token = $this->getTokenFromQuery($request, $this->queryParam);
99
        }
100
101 24
        $prefix = $this->tokenPrefix;
102 24
        if ($prefix !== null && is_string($token)) {
103 18
            return $this->stripTokenPrefix($token, $prefix);
104
        }
105
106 6
        return $token;
107
    }
108
109
    /**
110
     * Strips a prefix from a token
111
     *
112
     * @param string $token Token string
113
     * @param string $prefix Prefix to strip
114
     * @return string
115
     */
116 18
    protected function stripTokenPrefix(string $token, string $prefix): string
117
    {
118 18
        return str_ireplace($prefix . ' ', '', $token);
119
    }
120
121
    /**
122
     * Gets the token from the request headers
123
     *
124
     * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information.
125
     * @param string|null $headerLine Header name
126
     * @return string|null
127
     */
128 24
    protected function getTokenFromHeader(ServerRequestInterface $request, ?string $headerLine): ?string
129
    {
130 24
        if (!empty($headerLine)) {
131 21
            $header = $request->getHeaderLine($headerLine);
132 21
            if (!empty($header)) {
133 9
                return $header;
134
            }
135
        }
136
137 18
        return null;
138
    }
139
140
    /**
141
     * Gets the token from the request headers
142
     *
143
     * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information.
144
     * @param string|null $queryParam Request query parameter name
145
     * @return string|null
146
     */
147 18
    protected function getTokenFromQuery(ServerRequestInterface $request, ?string $queryParam): ?string
148
    {
149 18
        $queryParams = $request->getQueryParams();
150
151 18
        if (empty($queryParams[$queryParam])) {
152 3
            return null;
153
        }
154
155 15
        return $queryParams[$queryParam];
156
    }
157
158
    /**
159
     * Authenticates the identity contained in a request. Will use the `config.userModel`, and `config.fields`
160
     * to find POST data that is used to find a matching record in the `config.userModel`. Will return false if
161
     * there is no post data, either username or password is missing, or if the scope conditions have not been met.
162
     *
163
     * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information.
164
     * @return \Phauthentic\Authentication\Authenticator\ResultInterface
165
     */
166 9
    public function authenticate(ServerRequestInterface $request): ResultInterface
167
    {
168 9
        $token = $this->getToken($request);
169 9
        if ($token === null) {
170 3
            return new Result(null, Result::FAILURE_CREDENTIALS_MISSING);
171
        }
172
173 9
        $user = $this->identifier->identify([
174 9
            IdentifierInterface::CREDENTIAL_TOKEN => $token
175
        ]);
176
177 9
        if (empty($user)) {
178 6
            return new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND, $this->identifier->getErrors());
179
        }
180
181 9
        return new Result($user, Result::SUCCESS);
182
    }
183
184
    /**
185
     * No-op method.
186
     *
187
     * @param \Psr\Http\Message\ServerRequestInterface $request A request object.
188
     * @return void
189
     */
190
    public function unauthorizedChallenge(ServerRequestInterface $request): void
191
    {
192
    }
193
}
194