Failed Conditions
Push — ng ( 6e48f5...81cfdf )
by Florent
04:01
created

aClientIdIsSetButTheAuthenticationMethodIsNotSupportedByTheClient()   B

Complexity

Conditions 2
Paths 3

Size

Total Lines 36
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 36
rs 8.8571
c 0
b 0
f 0
cc 2
eloc 27
nc 3
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2018 Spomky-Labs
9
 *
10
 * This software may be modified and distributed under the terms
11
 * of the MIT license.  See the LICENSE file for details.
12
 */
13
14
namespace OAuth2Framework\Component\Server\TokenEndpoint\Tests;
15
16
use Interop\Http\Server\RequestHandlerInterface;
17
use OAuth2Framework\Component\Server\Core\Client\Client;
18
use OAuth2Framework\Component\Server\Core\Client\ClientId;
19
use OAuth2Framework\Component\Server\Core\Client\ClientRepository;
20
use OAuth2Framework\Component\Server\Core\DataBag\DataBag;
21
use OAuth2Framework\Component\Server\Core\Response\OAuth2Exception;
22
use OAuth2Framework\Component\Server\TokenEndpoint\AuthenticationMethod\AuthenticationMethod;
23
use OAuth2Framework\Component\Server\TokenEndpoint\AuthenticationMethod\AuthenticationMethodManager;
24
use OAuth2Framework\Component\Server\TokenEndpoint\AuthenticationMethod\ClientSecretBasic;
25
use OAuth2Framework\Component\Server\TokenEndpoint\ClientAuthenticationMiddleware;
26
use PHPUnit\Framework\TestCase;
27
use Prophecy\Argument;
28
use Psr\Http\Message\ResponseInterface;
29
use Psr\Http\Message\ServerRequestInterface;
30
31
/**
32
 * @group TokenEndpoint
33
 * @group ClientAuthenticationMiddleware
34
 */
35
final class ClientAuthenticationMiddlewareTest extends TestCase
36
{
37
    /**
38
     * @test
39
     */
40
    public function noClientIsFoundInTheRequest()
41
    {
42
        $response = $this->prophesize(ResponseInterface::class);
43
        $request = $this->prophesize(ServerRequestInterface::class);
44
        $request->getHeader('Authorization')->willReturn([])->shouldBeCalled();
45
        $handler = $this->prophesize(RequestHandlerInterface::class);
46
        $clientRepository = $this->prophesize(ClientRepository::class);
47
        $handler->handle(Argument::type(ServerRequestInterface::class))
48
            ->shouldBeCalled()
49
            ->willReturn($response->reveal())
50
        ;
51
52
        $this->getClientAuthenticationMiddleware($clientRepository->reveal())->process($request->reveal(), $handler->reveal());
53
    }
54
55
    /**
56
     * @test
57
     */
58
    public function aClientIdIsSetButTheClientDoesNotExist()
59
    {
60
        $request = $this->prophesize(ServerRequestInterface::class);
61
        $request->getHeader('Authorization')
62
            ->willReturn([
63
                'Basic '.base64_encode('FOO:BAR'),
64
            ])
65
            ->shouldBeCalled();
66
        $handler = $this->prophesize(RequestHandlerInterface::class);
67
        $clientRepository = $this->prophesize(ClientRepository::class);
68
        $clientRepository->find(Argument::type(ClientId::class))->willReturn(null)->shouldBeCalled();
69
        $handler->handle(Argument::type(ServerRequestInterface::class))
70
            ->shouldNotBeCalled()
71
        ;
72
73
        try {
74
            $this->getClientAuthenticationMiddleware($clientRepository->reveal())->process($request->reveal(), $handler->reveal());
75
            $this->fail('An OAuth2 exception should be thrown.');
76
        } catch (OAuth2Exception $e) {
77
            self::assertEquals(401, $e->getCode());
78
            self::assertEquals([
79
                'error' => 'invalid_client',
80
                'error_description' => 'Unknown client or client not authenticated.',
81
            ], $e->getData());
82
        }
83
    }
84
85
    /**
86
     * @test
87
     */
88
    public function aClientIdIsSetButTheClientIsDeleted()
89
    {
90
        $client = Client::createEmpty();
91
        $client = $client->create(
92
            ClientId::create('FOO'),
93
            DataBag::create([]),
94
            null
95
        );
96
        $client = $client->markAsDeleted();
97
        $client->eraseMessages();
98
99
        $request = $this->prophesize(ServerRequestInterface::class);
100
        $request->getHeader('Authorization')
101
            ->willReturn([
102
                'Basic '.base64_encode('FOO:BAR'),
103
            ])
104
            ->shouldBeCalled();
105
        $handler = $this->prophesize(RequestHandlerInterface::class);
106
        $clientRepository = $this->prophesize(ClientRepository::class);
107
        $clientRepository->find(Argument::type(ClientId::class))->willReturn($client)->shouldBeCalled();
108
        $handler->handle(Argument::type(ServerRequestInterface::class))
109
            ->shouldNotBeCalled()
110
        ;
111
112
        try {
113
            $this->getClientAuthenticationMiddleware($clientRepository->reveal())->process($request->reveal(), $handler->reveal());
114
            $this->fail('An OAuth2 exception should be thrown.');
115
        } catch (OAuth2Exception $e) {
116
            self::assertEquals(401, $e->getCode());
117
            self::assertEquals([
118
                'error' => 'invalid_client',
119
                'error_description' => 'Unknown client or client not authenticated.',
120
            ], $e->getData());
121
        }
122
    }
123
124
    /**
125
     * @test
126
     */
127
    public function aClientIdIsSetButTheClientCredentialsExpired()
128
    {
129
        $client = Client::createEmpty();
130
        $client = $client->create(
131
            ClientId::create('FOO'),
132
            DataBag::create([
133
                'token_endpoint_auth_method' => 'client_secret_basic',
134
                'client_secret' => 'BAR',
135
                'client_secret_expires_at' => time() - 1,
136
            ]),
137
            null
138
        );
139
        $client->eraseMessages();
140
141
        $request = $this->prophesize(ServerRequestInterface::class);
142
        $request->getHeader('Authorization')
143
            ->willReturn([
144
                'Basic '.base64_encode('FOO:BAR'),
145
            ])
146
            ->shouldBeCalled();
147
        $handler = $this->prophesize(RequestHandlerInterface::class);
148
        $clientRepository = $this->prophesize(ClientRepository::class);
149
        $clientRepository->find(Argument::type(ClientId::class))->willReturn($client)->shouldBeCalled();
150
        $handler->handle(Argument::type(ServerRequestInterface::class))
151
            ->shouldNotBeCalled()
152
        ;
153
154
        try {
155
            $this->getClientAuthenticationMiddleware($clientRepository->reveal())->process($request->reveal(), $handler->reveal());
156
            $this->fail('An OAuth2 exception should be thrown.');
157
        } catch (OAuth2Exception $e) {
158
            self::assertEquals(401, $e->getCode());
159
            self::assertEquals([
160
                'error' => 'invalid_client',
161
                'error_description' => 'Client credentials expired.',
162
            ], $e->getData());
163
        }
164
    }
165
166
    /**
167
     * @test
168
     */
169
    public function aClientIdIsSetButTheAuthenticationMethodIsNotSupportedByTheClient()
170
    {
171
        $client = Client::createEmpty();
172
        $client = $client->create(
173
            ClientId::create('FOO'),
174
            DataBag::create([
175
                'token_endpoint_auth_method' => 'none',
176
            ]),
177
            null
178
        );
179
        $client->eraseMessages();
180
181
        $request = $this->prophesize(ServerRequestInterface::class);
182
        $request->getHeader('Authorization')
183
            ->willReturn([
184
                'Basic '.base64_encode('FOO:BAR'),
185
            ])
186
            ->shouldBeCalled();
187
        $handler = $this->prophesize(RequestHandlerInterface::class);
188
        $clientRepository = $this->prophesize(ClientRepository::class);
189
        $clientRepository->find(Argument::type(ClientId::class))->willReturn($client)->shouldBeCalled();
190
        $handler->handle(Argument::type(ServerRequestInterface::class))
191
            ->shouldNotBeCalled()
192
        ;
193
194
        try {
195
            $this->getClientAuthenticationMiddleware($clientRepository->reveal())->process($request->reveal(), $handler->reveal());
196
            $this->fail('An OAuth2 exception should be thrown.');
197
        } catch (OAuth2Exception $e) {
198
            self::assertEquals(401, $e->getCode());
199
            self::assertEquals([
200
                'error' => 'invalid_client',
201
                'error_description' => 'Unknown client or client not authenticated.',
202
            ], $e->getData());
203
        }
204
    }
205
206
    /**
207
     * @test
208
     */
209
    public function aClientIdIsSetButTheClientIsNotAuthenticated()
210
    {
211
        $client = Client::createEmpty();
212
        $client = $client->create(
213
            ClientId::create('FOO'),
214
            DataBag::create([
215
                'token_endpoint_auth_method' => 'client_secret_basic',
216
                'client_secret' => 'BAR',
217
            ]),
218
            null
219
        );
220
        $client->eraseMessages();
221
222
        $request = $this->prophesize(ServerRequestInterface::class);
223
        $request->getHeader('Authorization')
224
            ->willReturn([
225
                'Basic '.base64_encode('FOO:BAD_SECRET'),
226
            ])
227
            ->shouldBeCalled();
228
        $handler = $this->prophesize(RequestHandlerInterface::class);
229
        $clientRepository = $this->prophesize(ClientRepository::class);
230
        $clientRepository->find(Argument::type(ClientId::class))->willReturn($client)->shouldBeCalled();
231
        $handler->handle(Argument::type(ServerRequestInterface::class))
232
            ->shouldNotBeCalled()
233
        ;
234
235
        try {
236
            $this->getClientAuthenticationMiddleware($clientRepository->reveal())->process($request->reveal(), $handler->reveal());
237
            $this->fail('An OAuth2 exception should be thrown.');
238
        } catch (OAuth2Exception $e) {
239
            self::assertEquals(401, $e->getCode());
240
            self::assertEquals([
241
                'error' => 'invalid_client',
242
                'error_description' => 'Unknown client or client not authenticated.',
243
            ], $e->getData());
244
        }
245
    }
246
247
    /**
248
     * @test
249
     */
250
    public function aClientIsFullyAuthenticated()
251
    {
252
        $client = Client::createEmpty();
253
        $client = $client->create(
254
            ClientId::create('FOO'),
255
            DataBag::create([
256
                'token_endpoint_auth_method' => 'client_secret_basic',
257
                'client_secret' => 'BAR',
258
            ]),
259
            null
260
        );
261
        $client->eraseMessages();
262
263
        $response = $this->prophesize(ResponseInterface::class);
264
        $request = $this->prophesize(ServerRequestInterface::class);
265
        $request->getHeader('Authorization')
266
            ->willReturn([
267
                'Basic '.base64_encode('FOO:BAR'),
268
            ])
269
            ->shouldBeCalled();
270
        $request->withAttribute('client', $client)->shouldBeCalled()->willReturn($request->reveal());
271
        $request->withAttribute('client_authentication_method', Argument::type(AuthenticationMethod::class))->shouldBeCalled()->willReturn($request->reveal());
272
        $request->withAttribute('client_credentials', 'BAR')->shouldBeCalled()->willReturn($request->reveal());
273
        $handler = $this->prophesize(RequestHandlerInterface::class);
274
        $clientRepository = $this->prophesize(ClientRepository::class);
275
        $clientRepository->find(Argument::type(ClientId::class))->willReturn($client)->shouldBeCalled();
276
        $handler->handle(Argument::type(ServerRequestInterface::class))
277
            ->shouldBeCalled()
278
            ->willReturn($response->reveal())
279
        ;
280
281
        $this->getClientAuthenticationMiddleware($clientRepository->reveal())->process($request->reveal(), $handler->reveal());
282
    }
283
284
    /**
285
     * @param ClientRepository $clientRepository
286
     *
287
     * @return ClientAuthenticationMiddleware
288
     */
289
    private function getClientAuthenticationMiddleware(ClientRepository $clientRepository): ClientAuthenticationMiddleware
290
    {
291
        $authenticationMethodManager = new AuthenticationMethodManager();
292
        $authenticationMethodManager->add(new ClientSecretBasic('Real'));
293
294
        $clientAuthenticationMiddleware = new ClientAuthenticationMiddleware(
295
            $clientRepository,
296
            $authenticationMethodManager
297
        );
298
299
        return $clientAuthenticationMiddleware;
300
    }
301
}
302