HttpBasicAuthenticator   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 101
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 8
eloc 24
c 0
b 0
f 0
dl 0
loc 101
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A supports() 0 4 1
A __construct() 0 5 1
A authenticate() 0 10 1
A onAuthenticationFailure() 0 14 1
A createToken() 0 9 1
A start() 0 5 1
A clear() 0 2 1
A onAuthenticationSuccess() 0 3 1
1
<?php
2
3
/**
4
 * This file is part of php-scaffold
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace Slick\WebStack\Infrastructure\Http\Authenticator;
13
14
use Psr\Http\Message\ResponseInterface;
15
use Psr\Http\Message\ServerRequestInterface;
16
use Psr\Log\LoggerInterface;
17
use Slick\Http\Message\Response;
18
use Slick\WebStack\Domain\Security\Authentication\Token\UsernamePasswordToken;
19
use Slick\WebStack\Domain\Security\Authentication\TokenInterface;
20
use Slick\WebStack\Domain\Security\Exception\AuthenticationException;
21
use Slick\WebStack\Domain\Security\Http\AuthenticationEntryPointInterface;
22
use Slick\WebStack\Domain\Security\Http\Authenticator\Passport;
23
use Slick\WebStack\Domain\Security\Http\Authenticator\Passport\Badge\Credentials\PasswordCredentials;
24
use Slick\WebStack\Domain\Security\Http\Authenticator\Passport\Badge\UserBadge;
25
use Slick\WebStack\Domain\Security\Http\Authenticator\PassportInterface;
26
use Slick\WebStack\Domain\Security\Http\AuthenticatorInterface;
27
use Slick\WebStack\Domain\Security\SecurityException;
28
use Slick\WebStack\Domain\Security\User\UserProviderInterface;
29
use Slick\WebStack\Domain\Security\UserInterface;
30
31
/**
32
 * HttpBasicAuthenticator
33
 *
34
 * @package Slick\WebStack\Infrastructure\Http\Authenticator
35
 * @template TUser of UserInterface
36
 * @implements AuthenticatorInterface<TUser>
37
 */
38
final class HttpBasicAuthenticator implements AuthenticatorInterface, AuthenticationEntryPointInterface
39
{
40
41
    use AuthenticatorHandlerTrait;
42
43
    /**
44
     * Creates a HttpBasicAuthenticator
45
     *
46
     * @param string $realm
47
     * @param UserProviderInterface<TUser> $provider
48
     * @param LoggerInterface|null $logger
49
     */
50
    public function __construct(
51
        private readonly string                $realm,
52
        private readonly UserProviderInterface $provider,
53
        private readonly ?LoggerInterface      $logger = null
54
    ) {
55
    }
56
57
    /**
58
     * @inheritDoc
59
     */
60
    public function supports(ServerRequestInterface $request): bool
61
    {
62
        $serverParams = $request->getServerParams() ?? [];
63
        return array_key_exists('PHP_AUTH_USER', $serverParams);
64
    }
65
66
    /**
67
     * @inheritDoc
68
     * @return Passport<UserInterface>
69
     */
70
    public function authenticate(ServerRequestInterface $request): Passport
71
    {
72
        $serverParams = $request->getServerParams() ?? [];
73
        $username = $serverParams['PHP_AUTH_USER'] ?? null;
74
        $password = $serverParams['PHP_AUTH_PW'] ?? '';
75
76
        $userBadge = new UserBadge($username, $this->provider->loadUserByIdentifier(...));
0 ignored issues
show
Bug introduced by
It seems like $username can also be of type null; however, parameter $userIdentifier of Slick\WebStack\Domain\Se...serBadge::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

76
        $userBadge = new UserBadge(/** @scrutinizer ignore-type */ $username, $this->provider->loadUserByIdentifier(...));
Loading history...
77
        $credentials = new PasswordCredentials($password);
78
79
        return new Passport($userBadge, $credentials);
80
    }
81
82
    /**
83
     * @inheritDoc
84
     * @throws SecurityException
85
     */
86
    public function createToken(PassportInterface $passport): UsernamePasswordToken
87
    {
88
        $authToken = new UsernamePasswordToken($passport->user(), $passport->user()->roles());
89
        $authToken->withAttributes([
90
        'IS_AUTHENTICATED_FULLY' => 'true',
91
        'IS_AUTHENTICATED_REMEMBERED' => 'false',
92
        'IS_AUTHENTICATED' => 'true'
93
        ]);
94
        return $authToken;
95
    }
96
97
    /**
98
     * @inheritDoc
99
     */
100
    public function onAuthenticationSuccess(ServerRequestInterface $request, TokenInterface $token): ?ResponseInterface
101
    {
102
        return null;
103
    }
104
105
    /**
106
     * @inheritDoc
107
     */
108
    public function onAuthenticationFailure(
109
        ServerRequestInterface $request,
110
        AuthenticationException $exception
111
    ): ResponseInterface {
112
        $serverParams = $request->getServerParams() ?? [];
113
        $this->logger?->info(
114
            'Basic authentication failed for user.',
115
            [
116
            'username' => $serverParams['PHP_AUTH_USER'] ?? '',
117
            'exception' => $exception,
118
            ]
119
        );
120
121
        return $this->start($request);
122
    }
123
124
    /**
125
     * @inheritDoc
126
     */
127
    public function start(
128
        ServerRequestInterface $request,
129
        ?AuthenticationException $authException = null
130
    ): ResponseInterface {
131
        return new Response(401, 'Unauthorized', ['WWW-Authenticate' => sprintf('Basic realm="%s"', $this->realm)]);
132
    }
133
134
    /**
135
     * @inheritDoc
136
     */
137
    public function clear(): void
138
    {
139
        // Do nothing here
140
    }
141
}
142