Failed Conditions
Push — ng ( 625bbc...a06888 )
by Florent
08:03
created

TokenEndpointTest   B

Complexity

Total Complexity 13

Size/Duplication

Total Lines 223
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 16

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 16
dl 0
loc 223
rs 8.4614
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
B unauthenticatedClient() 0 24 2
B theClientIsNotAllowedToUseTheGrantType() 0 32 2
B theTokenRequestIsValidAndAnAccessTokenIsIssued() 0 41 1
A getTokenEndpoint() 0 14 2
A getClientRepository() 0 21 2
A getUserAccountRepository() 0 10 2
B getAccessTokenRepository() 0 31 2
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\TokenEndpoint\Tests;
15
16
use Http\Message\MessageFactory\GuzzleMessageFactory;
17
use Psr\Http\Server\RequestHandlerInterface;
18
use OAuth2Framework\Component\Core\AccessToken\AccessToken;
19
use OAuth2Framework\Component\Core\AccessToken\AccessTokenId;
20
use OAuth2Framework\Component\Core\AccessToken\AccessTokenRepository;
21
use OAuth2Framework\Component\Core\Client\Client;
22
use OAuth2Framework\Component\Core\Client\ClientId;
23
use OAuth2Framework\Component\Core\Client\ClientRepository;
24
use OAuth2Framework\Component\Core\DataBag\DataBag;
25
use OAuth2Framework\Component\Core\ResourceOwner\ResourceOwnerId;
26
use OAuth2Framework\Component\Core\Exception\OAuth2Exception;
27
use OAuth2Framework\Component\Core\UserAccount\UserAccountId;
28
use OAuth2Framework\Component\Core\UserAccount\UserAccountRepository;
29
use OAuth2Framework\Component\TokenEndpoint\Extension\TokenEndpointExtensionManager;
30
use OAuth2Framework\Component\TokenEndpoint\TokenEndpoint;
31
use OAuth2Framework\Component\TokenType\TokenType;
32
use PHPUnit\Framework\TestCase;
33
use Prophecy\Argument;
34
use Psr\Http\Message\ServerRequestInterface;
35
36
/**
37
 * @group TokenEndpoint
38
 */
39
class TokenEndpointTest extends TestCase
40
{
41
    /**
42
     * @test
43
     */
44
    public function unauthenticatedClient()
45
    {
46
        $request = $this->prophesize(ServerRequestInterface::class);
47
        $request->getAttribute('grant_type')
48
            ->willReturn(new FooGrantType())
49
            ->shouldBeCalled()
50
        ;
51
        $request->getAttribute('client')
52
            ->willReturn(null)
53
            ->shouldBeCalled()
54
        ;
55
56
        $handler = $this->prophesize(RequestHandlerInterface::class);
57
58
        try {
59
            $this->getTokenEndpoint()->process($request->reveal(), $handler->reveal());
60
        } catch (OAuth2Exception $e) {
61
            self::assertEquals(401, $e->getCode());
62
            self::assertEquals([
63
                'error' => 'invalid_client',
64
                'error_description' => 'Client authentication failed.',
65
            ], $e->getData());
66
        }
67
    }
68
69
    /**
70
     * @test
71
     */
72
    public function theClientIsNotAllowedToUseTheGrantType()
73
    {
74
        $client = Client::createEmpty();
75
        $client = $client->create(
76
            ClientId::create('CLIENT_ID'),
77
            DataBag::create([]),
78
            UserAccountId::create('OWNER_ID')
79
        );
80
        $client->eraseMessages();
81
82
        $request = $this->prophesize(ServerRequestInterface::class);
83
        $request->getAttribute('grant_type')
84
            ->willReturn(new FooGrantType())
85
            ->shouldBeCalled()
86
        ;
87
        $request->getAttribute('client')
88
            ->willReturn($client)
89
            ->shouldBeCalled()
90
        ;
91
92
        $handler = $this->prophesize(RequestHandlerInterface::class);
93
94
        try {
95
            $this->getTokenEndpoint()->process($request->reveal(), $handler->reveal());
96
        } catch (OAuth2Exception $e) {
97
            self::assertEquals(400, $e->getCode());
98
            self::assertEquals([
99
                'error' => 'unauthorized_client',
100
                'error_description' => 'The grant type "foo" is unauthorized for this client.',
101
            ], $e->getData());
102
        }
103
    }
104
105
    /**
106
     * @test
107
     */
108
    public function theTokenRequestIsValidAndAnAccessTokenIsIssued()
109
    {
110
        $client = Client::createEmpty();
111
        $client = $client->create(
112
            ClientId::create('CLIENT_ID'),
113
            DataBag::create([
114
                'grant_types' => ['foo'],
115
            ]),
116
            UserAccountId::create('OWNER_ID')
117
        );
118
        $client->eraseMessages();
119
120
        $request = $this->prophesize(ServerRequestInterface::class);
121
        $request->getAttribute('grant_type')
122
            ->willReturn(new FooGrantType())
123
            ->shouldBeCalled()
124
        ;
125
        $request->getAttribute('client')
126
            ->willReturn($client)
127
            ->shouldBeCalled()
128
        ;
129
130
        $tokenType = $this->prophesize(TokenType::class);
131
        $tokenType->name()->willReturn('TOKEN_TYPE')->shouldBeCalled();
132
        $tokenType->getAdditionalInformation()->willReturn(['token_type_foo' => 'token_type_bar'])->shouldBeCalled();
133
        $request->getAttribute('token_type')
134
            ->willReturn($tokenType->reveal())
135
            ->shouldBeCalled()
136
        ;
137
138
        $handler = $this->prophesize(RequestHandlerInterface::class);
139
        $handler->handle(Argument::type(ServerRequestInterface::class))
140
            ->shouldNotBeCalled();
141
142
        $response = $this->getTokenEndpoint()->process($request->reveal(), $handler->reveal());
143
        $response->getBody()->rewind();
144
        $body = $response->getBody()->getContents();
145
146
        self::assertEquals(200, $response->getStatusCode());
147
        self::assertRegexp('/^\{"token_type_foo"\:"token_type_bar","token_type"\:"TOKEN_TYPE","access_token"\:"ACCESS_TOKEN_ID","expires_in"\:\d{4}\}$/', $body);
148
    }
149
150
    /**
151
     * @var null|TokenEndpoint
152
     */
153
    private $tokenEndpoint = null;
154
155
    /**
156
     * @return TokenEndpoint
157
     */
158
    private function getTokenEndpoint(): TokenEndpoint
159
    {
160
        if (null === $this->tokenEndpoint) {
161
            $this->tokenEndpoint = new TokenEndpoint(
162
                $this->getClientRepository(),
163
                $this->getUserAccountRepository(),
164
                new TokenEndpointExtensionManager(),
165
                new GuzzleMessageFactory(),
166
                $this->getAccessTokenRepository()
167
            );
168
        }
169
170
        return $this->tokenEndpoint;
171
    }
172
173
    /**
174
     * @var null|ClientRepository
175
     */
176
    private $clientRepository = null;
177
178
    /**
179
     * @return ClientRepository
180
     */
181
    private function getClientRepository(): ClientRepository
182
    {
183
        if (null === $this->clientRepository) {
184
            $client = Client::createEmpty();
185
            $client = $client->create(
186
                ClientId::create('CLIENT_ID'),
187
                DataBag::create([
188
                    'grant_types' => ['foo'],
189
                ]),
190
                UserAccountId::create('OWNER_ID')
191
            );
192
            $client->eraseMessages();
193
194
            $clientRepository = $this->prophesize(ClientRepository::class);
195
            $clientRepository->find(Argument::type(ClientId::class))->willReturn($client);
196
197
            $this->clientRepository = $clientRepository->reveal();
198
        }
199
200
        return $this->clientRepository;
201
    }
202
203
    /**
204
     * @var null|UserAccountRepository
205
     */
206
    private $userAccountRepository = null;
207
208
    /**
209
     * @return UserAccountRepository
210
     */
211
    private function getUserAccountRepository(): UserAccountRepository
212
    {
213
        if (null === $this->userAccountRepository) {
214
            $userAccountRepository = $this->prophesize(UserAccountRepository::class);
215
216
            $this->userAccountRepository = $userAccountRepository->reveal();
217
        }
218
219
        return $this->userAccountRepository;
220
    }
221
222
    /**
223
     * @var null|AccessTokenRepository
224
     */
225
    private $accessTokenRepository = null;
226
227
    /**
228
     * @return AccessTokenRepository
229
     */
230
    private function getAccessTokenRepository(): AccessTokenRepository
231
    {
232
        if (null === $this->accessTokenRepository) {
233
            $accessTokenRepository = $this->prophesize(AccessTokenRepository::class);
234
            $accessTokenRepository->create(
235
                Argument::type(ResourceOwnerId::class),
236
                Argument::type(ClientId::class),
237
                Argument::type(DataBag::class),
238
                Argument::type(DataBag::class),
239
                null
240
            )->will(function ($args) {
241
                $accesstoken = AccessToken::createEmpty();
242
                $accesstoken = $accesstoken->create(
243
                    AccessTokenId::create('ACCESS_TOKEN_ID'),
244
                    $args[0],
245
                    $args[1],
246
                    $args[2],
247
                    $args[3],
248
                    new \DateTimeImmutable('now + 1 hour'),
249
                    $args[4]
250
                );
251
252
                return $accesstoken;
253
            });
254
            $accessTokenRepository->save(Argument::type(AccessToken::class))->willReturn(null);
255
256
            $this->accessTokenRepository = $accessTokenRepository->reveal();
257
        }
258
259
        return $this->accessTokenRepository;
260
    }
261
}
262