|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
declare(strict_types=1); |
|
4
|
|
|
|
|
5
|
|
|
namespace AtlassianConnectBundle\Tests\Security; |
|
6
|
|
|
|
|
7
|
|
|
use AtlassianConnectBundle\Entity\Tenant; |
|
8
|
|
|
use AtlassianConnectBundle\Security\JWTAuthenticator; |
|
9
|
|
|
use AtlassianConnectBundle\Security\JWTSecurityHelperInterface; |
|
10
|
|
|
use AtlassianConnectBundle\Security\JWTUserProvider; |
|
11
|
|
|
use AtlassianConnectBundle\Security\JWTUserProviderInterface; |
|
12
|
|
|
use PHPUnit\Framework\MockObject\MockObject; |
|
13
|
|
|
use PHPUnit\Framework\TestCase; |
|
14
|
|
|
use Symfony\Component\HttpFoundation\Request; |
|
15
|
|
|
use Symfony\Component\HttpKernel\Kernel; |
|
16
|
|
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; |
|
17
|
|
|
use Symfony\Component\Security\Core\Exception\AuthenticationException; |
|
18
|
|
|
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException; |
|
19
|
|
|
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; |
|
20
|
|
|
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport; |
|
21
|
|
|
|
|
22
|
|
|
/** |
|
23
|
|
|
* Class JWTAuthenticatorTest |
|
24
|
|
|
*/ |
|
25
|
|
|
final class JWTAuthenticatorTest extends TestCase |
|
26
|
|
|
{ |
|
27
|
|
|
/** |
|
28
|
|
|
* @var JWTUserProviderInterface|MockObject |
|
29
|
|
|
*/ |
|
30
|
|
|
private $userProvider; |
|
31
|
|
|
|
|
32
|
|
|
/** |
|
33
|
|
|
* @var JWTSecurityHelperInterface|MockObject |
|
34
|
|
|
*/ |
|
35
|
|
|
private $securityHelper; |
|
36
|
|
|
|
|
37
|
|
|
/** |
|
38
|
|
|
* @var JWTAuthenticator |
|
39
|
|
|
*/ |
|
40
|
|
|
private $jwtAuthenticator; |
|
41
|
|
|
|
|
42
|
|
|
protected function setUp(): void |
|
43
|
|
|
{ |
|
44
|
|
|
if (Kernel::VERSION_ID < 50100) { |
|
45
|
|
|
$this->markTestSkipped('This test only works with the new authenticator mechanism'); |
|
46
|
|
|
} |
|
47
|
|
|
|
|
48
|
|
|
$this->userProvider = $this->createMock(JWTUserProvider::class); |
|
49
|
|
|
$this->securityHelper = $this->createMock(JWTSecurityHelperInterface::class); |
|
50
|
|
|
$this->jwtAuthenticator = new JWTAuthenticator( |
|
51
|
|
|
$this->userProvider, |
|
52
|
|
|
$this->securityHelper |
|
53
|
|
|
); |
|
54
|
|
|
} |
|
55
|
|
|
|
|
56
|
|
|
/** |
|
57
|
|
|
* Tests if the request is supported |
|
58
|
|
|
*/ |
|
59
|
|
|
public function testSupportsRequest(): void |
|
60
|
|
|
{ |
|
61
|
|
|
$this->securityHelper |
|
62
|
|
|
->expects($this->once()) |
|
63
|
|
|
->method('supportsRequest') |
|
64
|
|
|
->with($request = new Request()) |
|
65
|
|
|
->willReturn(true); |
|
66
|
|
|
|
|
67
|
|
|
$this->assertTrue($this->jwtAuthenticator->supports($request)); |
|
68
|
|
|
} |
|
69
|
|
|
|
|
70
|
|
|
/** |
|
71
|
|
|
* Test the authenticate method |
|
72
|
|
|
*/ |
|
73
|
|
|
public function testAuthenticate(): void |
|
74
|
|
|
{ |
|
75
|
|
|
$token = [ |
|
76
|
|
|
'sub' => 'username', |
|
77
|
|
|
'iss' => 'key', |
|
78
|
|
|
]; |
|
79
|
|
|
|
|
80
|
|
|
$this->securityHelper |
|
81
|
|
|
->expects($this->once()) |
|
82
|
|
|
->method('getJWTToken') |
|
83
|
|
|
->with($request = new Request()) |
|
84
|
|
|
->willReturn('token'); |
|
85
|
|
|
|
|
86
|
|
|
$this->userProvider |
|
87
|
|
|
->expects($this->once()) |
|
88
|
|
|
->method('getDecodedToken') |
|
89
|
|
|
->with('token') |
|
90
|
|
|
->willReturn((object) $token); |
|
91
|
|
|
|
|
92
|
|
|
$this->userProvider |
|
93
|
|
|
->expects($this->once()) |
|
94
|
|
|
->method('loadUserByIdentifier') |
|
95
|
|
|
->with('key') |
|
96
|
|
|
->willReturn(new Tenant()); |
|
97
|
|
|
|
|
98
|
|
|
$result = $this->jwtAuthenticator->authenticate($request); |
|
99
|
|
|
$this->assertEquals( |
|
100
|
|
|
new SelfValidatingPassport(new UserBadge('username')), |
|
101
|
|
|
$result |
|
102
|
|
|
); |
|
103
|
|
|
} |
|
104
|
|
|
|
|
105
|
|
|
/** |
|
106
|
|
|
* Test if an exception is thrown when no jwt token is present |
|
107
|
|
|
*/ |
|
108
|
|
|
public function testAuthenticateHasNoJWTToken(): void |
|
109
|
|
|
{ |
|
110
|
|
|
$this->expectException(CustomUserMessageAuthenticationException::class); |
|
111
|
|
|
$this->expectExceptionMessage('JWT Token not provided'); |
|
112
|
|
|
|
|
113
|
|
|
$this->securityHelper |
|
114
|
|
|
->expects($this->once()) |
|
115
|
|
|
->method('getJWTToken') |
|
116
|
|
|
->with($request = new Request()) |
|
117
|
|
|
->willReturn(null); |
|
118
|
|
|
|
|
119
|
|
|
$this->jwtAuthenticator->authenticate($request); |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
/** |
|
123
|
|
|
* Test if an exception is thrown when no client key is present |
|
124
|
|
|
*/ |
|
125
|
|
|
public function testAuthenticateHasNoClientKey(): void |
|
126
|
|
|
{ |
|
127
|
|
|
$this->expectException(CustomUserMessageAuthenticationException::class); |
|
128
|
|
|
$this->expectExceptionMessage('API Key token does not exist'); |
|
129
|
|
|
|
|
130
|
|
|
$token = [ |
|
131
|
|
|
'sub' => 'username', |
|
132
|
|
|
'iss' => null, |
|
133
|
|
|
]; |
|
134
|
|
|
|
|
135
|
|
|
$this->securityHelper |
|
136
|
|
|
->expects($this->once()) |
|
137
|
|
|
->method('getJWTToken') |
|
138
|
|
|
->with($request = new Request()) |
|
139
|
|
|
->willReturn('token'); |
|
140
|
|
|
|
|
141
|
|
|
$this->userProvider |
|
142
|
|
|
->expects($this->once()) |
|
143
|
|
|
->method('getDecodedToken') |
|
144
|
|
|
->with('token') |
|
145
|
|
|
->willReturn((object) $token); |
|
146
|
|
|
|
|
147
|
|
|
$this->jwtAuthenticator->authenticate($request); |
|
148
|
|
|
} |
|
149
|
|
|
|
|
150
|
|
|
/** |
|
151
|
|
|
* test onAuthenticationFailure Method |
|
152
|
|
|
*/ |
|
153
|
|
|
public function testItSendsAResponseOnAuthenticationFailure(): void |
|
154
|
|
|
{ |
|
155
|
|
|
$response = $this->jwtAuthenticator->onAuthenticationFailure(new Request(), new AuthenticationException('Error')); |
|
156
|
|
|
|
|
157
|
|
|
$this->assertEquals('Authentication Failed: Error', $response->getContent()); |
|
158
|
|
|
$this->assertEquals(403, $response->getStatusCode()); |
|
159
|
|
|
} |
|
160
|
|
|
|
|
161
|
|
|
/** |
|
162
|
|
|
* test onAuthenticationSuccess method |
|
163
|
|
|
*/ |
|
164
|
|
|
public function testItDoesNotSendAResponseOnAuthenticationSuccess(): void |
|
165
|
|
|
{ |
|
166
|
|
|
$this->assertNull($this->jwtAuthenticator->onAuthenticationSuccess(new Request(), $this->createMock(TokenInterface::class), 'main')); |
|
|
|
|
|
|
167
|
|
|
} |
|
168
|
|
|
} |
|
169
|
|
|
|
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.