Passed
Pull Request — master (#52)
by Matthieu
04:27
created

JWTAuthenticatorTest::testGetUserWithoutClientKeyThrowsException()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nc 1
nop 0
dl 0
loc 17
rs 9.9
c 0
b 0
f 0
1
<?php declare(strict_types = 1);
2
3
namespace AtlassianConnectBundle\Tests\Security;
4
5
use AtlassianConnectBundle\Entity\Tenant;
6
use AtlassianConnectBundle\Security\JWTAuthenticator;
7
use AtlassianConnectBundle\Security\JWTSecurityHelperInterface;
8
use AtlassianConnectBundle\Security\JWTUserProvider;
9
use AtlassianConnectBundle\Security\JWTUserProviderInterface;
10
use PHPUnit\Framework\MockObject\MockObject;
11
use PHPUnit\Framework\TestCase;
12
use Symfony\Component\HttpFoundation\Request;
13
use Symfony\Component\HttpFoundation\Response;
14
use Symfony\Component\HttpKernel\Kernel;
15
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
16
use Symfony\Component\Security\Core\Exception\AuthenticationException;
17
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
18
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
19
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
20
21
/**
22
 * Class JWTAuthenticatorTest
23
 */
24
final class JWTAuthenticatorTest extends TestCase
25
{
26
    /**
27
     * @var JWTUserProviderInterface|MockObject
28
     */
29
    private $userProvider;
30
31
    /**
32
     * @var JWTSecurityHelperInterface|MockObject
33
     */
34
    private $securityHelper;
35
36
    /**
37
     * @var JWTAuthenticator
38
     */
39
    private $jwtAuthenticator;
40
41
    /**
42
     * Setup function
43
     */
44
    protected function setUp(): void
45
    {
46
        if (Kernel::VERSION_ID < 50100) {
47
            $this->markTestSkipped('This test only works with the new authenticator mechanism');
48
        }
49
50
        $this->userProvider = $this->createMock(JWTUserProvider::class);
51
        $this->securityHelper = $this->createMock(JWTSecurityHelperInterface::class);
52
        $this->jwtAuthenticator = new JWTAuthenticator(
53
            $this->userProvider,
54
            $this->securityHelper
55
        );
56
    }
57
58
    /**
59
     * Tests if the request is supported
60
     */
61
    public function testSupportsRequest(): void
62
    {
63
        $this->securityHelper
64
            ->expects($this->once())
65
            ->method('supportsRequest')
66
            ->with($request = new Request())
67
            ->willReturn(true);
68
69
        $this->assertTrue($this->jwtAuthenticator->supports($request));
70
    }
71
72
    /**
73
     * Test the authenticate method
74
     */
75
    public function testAuthenticate(): void
76
    {
77
        $token = [
78
            'sub' => 'username',
79
            'iss' => 'key',
80
        ];
81
82
        $this->securityHelper
83
            ->expects($this->once())
84
            ->method('getJWTToken')
85
            ->with($request = new Request())
86
            ->willReturn('token');
87
88
        $this->userProvider
89
            ->expects($this->once())
90
            ->method('getDecodedToken')
91
            ->with('token')
92
            ->willReturn((object) $token);
93
94
        $this->userProvider
95
            ->expects($this->once())
96
            ->method('loadUserByIdentifier')
97
            ->with('key')
98
            ->willReturn($tenant = new Tenant());
99
100
        $result = $this->jwtAuthenticator->authenticate($request);
101
102
        if (\class_exists(UserBadge::class)) {
103
            $this->assertEquals(
104
                new SelfValidatingPassport(new UserBadge('key')),
105
                $result
106
            );
107
        } else {
108
            $this->assertEquals(
109
                new SelfValidatingPassport($tenant),
0 ignored issues
show
Bug introduced by
$tenant of type AtlassianConnectBundle\Entity\Tenant is incompatible with the type Symfony\Component\Securi...assport\Badge\UserBadge expected by parameter $userBadge of Symfony\Component\Securi...Passport::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

109
                new SelfValidatingPassport(/** @scrutinizer ignore-type */ $tenant),
Loading history...
110
                $result
111
            );
112
        }
113
    }
114
115
    /**
116
     * Test if an exception is thrown when no jwt token is present
117
     */
118
    public function testAuthenticateHasNoJWTToken(): void
119
    {
120
        $this->expectException(CustomUserMessageAuthenticationException::class);
121
        $this->expectExceptionMessage('JWT Token not provided');
122
123
        $this->securityHelper
124
            ->expects($this->once())
125
            ->method('getJWTToken')
126
            ->with($request = new Request())
127
            ->willReturn(null);
128
129
        $this->jwtAuthenticator->authenticate($request);
130
    }
131
132
    /**
133
     * Test if an exception is thrown when no client key is present
134
     */
135
    public function testAuthenticateHasNoClientKey(): void
136
    {
137
        $this->expectException(CustomUserMessageAuthenticationException::class);
138
        $this->expectExceptionMessage('API Key token does not exist');
139
140
        $token = [
141
            'sub' => 'username',
142
            'iss' => null,
143
        ];
144
145
        $this->securityHelper
146
            ->expects($this->once())
147
            ->method('getJWTToken')
148
            ->with($request = new Request())
149
            ->willReturn('token');
150
151
        $this->userProvider
152
            ->expects($this->once())
153
            ->method('getDecodedToken')
154
            ->with('token')
155
            ->willReturn((object) $token);
156
157
        $this->jwtAuthenticator->authenticate($request);
158
    }
159
160
    /**
161
     * test onAuthenticationFailure Method
162
     */
163
    public function testItSendsAResponseOnAuthenticationFailure(): void
164
    {
165
        $response = $this->jwtAuthenticator->onAuthenticationFailure(new Request(), new AuthenticationException('Error'));
166
167
        $this->assertEquals('Authentication Failed: Error', $response->getContent());
168
        $this->assertEquals(403, $response->getStatusCode());
169
    }
170
171
    /**
172
     * test onAuthenticationSuccess method
173
     */
174
    public function testItDoesNotSendAResponseOnAuthenticationSuccess(): void
175
    {
176
        $this->assertNull($this->jwtAuthenticator->onAuthenticationSuccess(new Request(), $this->createMock(TokenInterface::class), 'main'));
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->jwtAuthenticator-...erface::class), 'main') targeting AtlassianConnectBundle\S...AuthenticationSuccess() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

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.

Loading history...
177
    }
178
179
    /**
180
     * test start method
181
     */
182
    public function testStartMethod(): void
183
    {
184
        $this->assertEquals(
185
            new Response('Authentication header required', 401),
186
            $this->jwtAuthenticator->start(new Request())
187
        );
188
    }
189
}
190