1
|
|
|
<?php declare(strict_types = 1); |
2
|
|
|
|
3
|
|
|
namespace AtlassianConnectBundle\Tests\Security; |
4
|
|
|
|
5
|
|
|
use AtlassianConnectBundle\Entity\Tenant; |
6
|
|
|
use AtlassianConnectBundle\Security\JWTSecurityHelperInterface; |
7
|
|
|
use AtlassianConnectBundle\Security\JWTUserProvider; |
8
|
|
|
use AtlassianConnectBundle\Security\JWTUserProviderInterface; |
9
|
|
|
use AtlassianConnectBundle\Security\LegacyJWTAuthenticator; |
10
|
|
|
use PHPUnit\Framework\MockObject\MockObject; |
11
|
|
|
use PHPUnit\Framework\TestCase; |
12
|
|
|
use Symfony\Component\HttpFoundation\Request; |
13
|
|
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; |
14
|
|
|
use Symfony\Component\Security\Core\Exception\AuthenticationException; |
15
|
|
|
use Symfony\Component\Security\Core\User\UserInterface; |
16
|
|
|
use Symfony\Component\Security\Core\User\UserProviderInterface; |
17
|
|
|
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* Class LegacyJWTAuthenticatorTest |
21
|
|
|
*/ |
22
|
|
|
final class LegacyJWTAuthenticatorTest extends TestCase |
23
|
|
|
{ |
24
|
|
|
/** |
25
|
|
|
* @var JWTSecurityHelperInterface|MockObject |
26
|
|
|
*/ |
27
|
|
|
private $securityHelper; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @var LegacyJWTAuthenticator |
31
|
|
|
*/ |
32
|
|
|
private $jwtAuthenticator; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Setup Before Class |
36
|
|
|
* |
37
|
|
|
* @return void |
38
|
|
|
*/ |
39
|
|
|
public static function setUpBeforeClass(): void |
40
|
|
|
{ |
41
|
|
|
if (!\class_exists(AbstractGuardAuthenticator::class)) { |
42
|
|
|
self::markTestSkipped('Test only applies to symfony/security-guard 5.4 or earlier'); |
43
|
|
|
} |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Setup method |
48
|
|
|
*/ |
49
|
|
|
public function setUp(): void |
50
|
|
|
{ |
51
|
|
|
$this->securityHelper = $this->createMock(JWTSecurityHelperInterface::class); |
52
|
|
|
|
53
|
|
|
$this->jwtAuthenticator = new LegacyJWTAuthenticator($this->securityHelper); |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Test start method |
58
|
|
|
*/ |
59
|
|
|
public function testItSendsA401WhenNoAuthenticationHeaderIsSet(): void |
60
|
|
|
{ |
61
|
|
|
$response = $this->jwtAuthenticator->start(new Request()); |
62
|
|
|
|
63
|
|
|
$this->assertEquals('Authentication header required', $response->getContent()); |
64
|
|
|
$this->assertEquals(401, $response->getStatusCode()); |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* Tests if the request is supported |
69
|
|
|
*/ |
70
|
|
|
public function testSupportsRequest(): void |
71
|
|
|
{ |
72
|
|
|
$this->securityHelper |
73
|
|
|
->expects($this->once()) |
74
|
|
|
->method('supportsRequest') |
75
|
|
|
->with($request = new Request()) |
76
|
|
|
->willReturn(true); |
77
|
|
|
|
78
|
|
|
$this->assertTrue($this->jwtAuthenticator->supports($request)); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Test if the getCredentials method returns a valid array |
83
|
|
|
*/ |
84
|
|
|
public function testGetsCredentials(): void |
85
|
|
|
{ |
86
|
|
|
$request = new Request(['jwt' => 'token']); |
87
|
|
|
$this->securityHelper |
88
|
|
|
->expects($this->once()) |
89
|
|
|
->method('getJWTToken') |
90
|
|
|
->with($request) |
91
|
|
|
->willReturn('token'); |
92
|
|
|
|
93
|
|
|
$this->assertSame(['jwt' => 'token'], $this->jwtAuthenticator->getCredentials($request)); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* Test if the getCredentials method returns null when no jwt token is passed |
98
|
|
|
*/ |
99
|
|
|
public function testGetsCredentialsTokenDoesNotExist(): void |
100
|
|
|
{ |
101
|
|
|
$request = new Request(); |
102
|
|
|
$this->securityHelper |
103
|
|
|
->expects($this->once()) |
104
|
|
|
->method('getJWTToken') |
105
|
|
|
->with($request) |
106
|
|
|
->willReturn(null); |
107
|
|
|
|
108
|
|
|
$this->assertNull($this->jwtAuthenticator->getCredentials($request)); |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* Test get user gets invalid user provider |
113
|
|
|
*/ |
114
|
|
|
public function testGetUserGetsInvalidUserProvider(): void |
115
|
|
|
{ |
116
|
|
|
$this->expectException(\InvalidArgumentException::class); |
117
|
|
|
$this->expectExceptionMessage('UserProvider must implement AtlassianConnectBundle\Security\JWTUserProviderInterface'); |
118
|
|
|
|
119
|
|
|
$userProvider = $this->createMock(UserProviderInterface::class); |
120
|
|
|
|
121
|
|
|
$this->jwtAuthenticator->getUser('credentials', $userProvider); |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
/** |
125
|
|
|
* Test get user without client key throws exception |
126
|
|
|
*/ |
127
|
|
|
public function testGetUserWithoutClientKeyThrowsException(): void |
128
|
|
|
{ |
129
|
|
|
$this->expectException(AuthenticationException::class); |
130
|
|
|
$this->expectExceptionMessage('API Key "token" does not exist.'); |
131
|
|
|
|
132
|
|
|
$token = [ |
133
|
|
|
'sub' => 'username', |
134
|
|
|
'iss' => null, |
135
|
|
|
]; |
136
|
|
|
|
137
|
|
|
$userProvider = $this->createMock(JWTUserProviderInterface::class); |
138
|
|
|
$userProvider |
139
|
|
|
->expects($this->once()) |
140
|
|
|
->method('getDecodedToken') |
141
|
|
|
->willReturn((object) $token); |
142
|
|
|
|
143
|
|
|
$this->jwtAuthenticator->getUser(['jwt' => 'token'], $userProvider); |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Test UserProvider with loadByIdentifier metdho |
148
|
|
|
*/ |
149
|
|
|
public function testUserProviderHasLoadMethod(): void |
150
|
|
|
{ |
151
|
|
|
$token = [ |
152
|
|
|
'iss' => 'iss', |
153
|
|
|
'sub' => 'username', |
154
|
|
|
]; |
155
|
|
|
|
156
|
|
|
$tenant = new Tenant(); |
157
|
|
|
|
158
|
|
|
$userProvider = $this->createMock(JWTUserProvider::class); |
159
|
|
|
$userProvider |
160
|
|
|
->expects($this->once()) |
161
|
|
|
->method('getDecodedToken') |
162
|
|
|
->willReturn((object) $token); |
163
|
|
|
|
164
|
|
|
$userProvider |
165
|
|
|
->expects($this->once()) |
166
|
|
|
->method('loadUserByIdentifier') |
167
|
|
|
->with('iss') |
168
|
|
|
->willReturn($tenant); |
169
|
|
|
|
170
|
|
|
$user = $this->jwtAuthenticator->getUser(['jwt' => 'token'], $userProvider); |
171
|
|
|
|
172
|
|
|
$this->assertInstanceOf(Tenant::class, $user); |
173
|
|
|
$this->assertEquals('username', $tenant->getUsername()); |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* Test if a user gets fetched |
178
|
|
|
*/ |
179
|
|
|
public function testGetsUser(): void |
180
|
|
|
{ |
181
|
|
|
$token = [ |
182
|
|
|
'iss' => 'iss', |
183
|
|
|
'sub' => 'username', |
184
|
|
|
]; |
185
|
|
|
|
186
|
|
|
$tenant = new Tenant(); |
187
|
|
|
|
188
|
|
|
$userProvider = $this->createMock(JWTUserProviderInterface::class); |
189
|
|
|
$userProvider |
190
|
|
|
->expects($this->once()) |
191
|
|
|
->method('getDecodedToken') |
192
|
|
|
->willReturn((object) $token); |
193
|
|
|
|
194
|
|
|
$userProvider |
195
|
|
|
->expects($this->once()) |
196
|
|
|
->method('loadUserByUsername') |
197
|
|
|
->with('iss') |
198
|
|
|
->willReturn($tenant); |
199
|
|
|
|
200
|
|
|
$user = $this->jwtAuthenticator->getUser(['jwt' => 'token'], $userProvider); |
201
|
|
|
|
202
|
|
|
$this->assertInstanceOf(Tenant::class, $user); |
203
|
|
|
$this->assertEquals('username', $tenant->getUsername()); |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* test checkCredentials method |
208
|
|
|
*/ |
209
|
|
|
public function testItChecksCredentials(): void |
210
|
|
|
{ |
211
|
|
|
$this->assertTrue($this->jwtAuthenticator->checkCredentials(null, $this->createMock(UserInterface::class))); |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* test onAuthenticationFailure Method |
216
|
|
|
*/ |
217
|
|
|
public function testItSendsAResponseOnAuthenticationFailure(): void |
218
|
|
|
{ |
219
|
|
|
$response = $this->jwtAuthenticator->onAuthenticationFailure(new Request(), new AuthenticationException('Error')); |
220
|
|
|
|
221
|
|
|
$this->assertEquals('Authentication Failed: Error', $response->getContent()); |
222
|
|
|
$this->assertEquals(403, $response->getStatusCode()); |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
/** |
226
|
|
|
* test onAuthenticationSuccess method |
227
|
|
|
*/ |
228
|
|
|
public function testItDoesNotSendAResponseOnAuthenticationSuccess(): void |
229
|
|
|
{ |
230
|
|
|
$this->assertNull($this->jwtAuthenticator->onAuthenticationSuccess(new Request(), $this->createMock(TokenInterface::class), 'main')); |
|
|
|
|
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
/** |
234
|
|
|
* test supportsRememberMe method |
235
|
|
|
*/ |
236
|
|
|
public function testItDoesNotSupportRememberMeFunctionality(): void |
237
|
|
|
{ |
238
|
|
|
$this->assertFalse($this->jwtAuthenticator->supportsRememberMe()); |
239
|
|
|
} |
240
|
|
|
} |
241
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.