Passed
Push — master ( 5ed34a...340187 )
by Alexandre
02:40
created

ClientPasswordAuthenticator   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 89
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 62.79%

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 3
dl 0
loc 89
ccs 27
cts 43
cp 0.6279
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A isPasswordAuthentication() 0 4 1
A support() 0 9 2
C authenticate() 0 51 12
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: Alexandre
5
 * Date: 07/01/2018
6
 * Time: 14:19
7
 */
8
9
namespace OAuth2\ClientAuthentication\Authenticators;
10
11
12
use OAuth2\Role\Client\Type\ClientPassword;
13
use OAuth2\Role\Client\Type\ConfidentialClient;
14
use OAuth2\Roles\ClientInterface;
15
use OAuth2\Roles\Clients\ConfidentialClientInterface;
16
use OAuth2\Storages\ClientStorageInterface;
17
use Psr\Http\Message\ServerRequestInterface;
18
19
class ClientPasswordAuthenticator implements ClientAuthenticatorInterface
20
{
21
    /**
22
     * @var ClientStorageInterface
23
     */
24
    private $clientStorage;
25
    /**
26
     * @var bool
27
     */
28
    private $supportCredentialsInBody;
29
30
    public function __construct(ClientStorageInterface $clientStorage, ?bool $supportCredentialsInBody = null)
31
    {
32
        $this->clientStorage = $clientStorage;
33
        $this->supportCredentialsInBody = $supportCredentialsInBody;
34
    }
35
36 1
    public function isPasswordAuthentication(): bool
37
    {
38 1
        return true;
39
    }
40
41 1
    public function support(ServerRequestInterface $request): bool
42
    {
43 1
        if ($request->hasHeader('Authorization')) {
44 1
            return true;
45
        }
46
47
        $body = $request->getParsedBody();
48
        return isset($body['client_id'], $body['client_secret']);
49
    }
50
51
    /**
52
     * @param ServerRequestInterface $request
53
     * @return ClientInterface
54
     * @throws \Exception
55
     */
56 1
    public function authenticate(ServerRequestInterface $request): ClientInterface
57
    {
58 1
        $identifier = null;
59 1
        $password = null;
60 1
        $useHTTPAuthenticationScheme = true;
61 1
        $body = $request->getParsedBody();
62 1
        if ($request->hasHeader('Authorization')) {
63
            // 2.3 The client MUST NOT use more than one authentication method in each request
64 1
            if (isset($body['client_secret'])) {
65
                throw new \Exception('Multiple authentication methods used');
66
            }
67
68 1
            $authorization = $request->getHeader('Authorization')[0] ?? '';
69 1
            $authorization = explode(' ', trim($authorization));
70 1
            $method = $authorization[0];
71 1
            if (strtolower($method) === 'basic') {
72 1
                $authorization = explode(':', base64_decode($authorization[1]));
73 1
                $identifier = $authorization[0] ?? null;
74 1
                $password = $authorization[1] ?? '';
75
            }
76
        } else {
77
            $identifier = $body['client_id'] ?? null;
78
            $password = $body['client_secret'] ?? '';
79
            $useHTTPAuthenticationScheme = false;
80
        }
81
82 1
        if (is_null($identifier)) {
83
            throw new \Exception('No client authentication included');
84
        }
85
86 1
        $client = $this->clientStorage->get($identifier);
87 1
        if (!$client) {
88
            throw new \Exception('Unknown client');
89
        }
90
91 1
        if (!$useHTTPAuthenticationScheme &&
92
            ($this->supportCredentialsInBody === false ||
93 1
                (is_null($this->supportCredentialsInBody) && $client->isHttpBasicAuthenticationSchemeSupported()))) {
94
            throw new \Exception('Authentication method is limited to HTTP Basic authentication scheme');
95
        }
96
97 1
        if (!$client instanceof ConfidentialClientInterface) {
98
            throw new \Exception('Unsupported authentication method');
99
        }
100
101 1
        if ($client->getPassword() !== $password) {
102
            throw new \Exception('Authentication failed');
103
        }
104
105 1
        return $client;
106
    }
107
}