TokenAuthenticator   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 166
Duplicated Lines 0 %

Test Coverage

Coverage 95.12%

Importance

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

9 Methods

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