Completed
Pull Request — master (#15)
by Oguzhan
02:36
created

willGetSingleKeyWhenKeyIdIsNull()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 0
1
<?php
2
/*
3
 * This file is part of the KleijnWeb\JwtBundle package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
namespace KleijnWeb\JwtBundle\Tests\Authenticator;
9
10
use KleijnWeb\JwtBundle\Authenticator\Authenticator;
11
use KleijnWeb\JwtBundle\Authenticator\JwtKey;
12
use KleijnWeb\JwtBundle\Authenticator\JwtToken;
13
use KleijnWeb\JwtBundle\User\UserInterface;
14
use Symfony\Component\HttpFoundation\Request;
15
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
16
use Symfony\Component\Security\Core\User\User;
17
18
/**
19
 * @author John Kleijn <[email protected]>
20
 */
21
class AuthenticatorTest extends \PHPUnit_Framework_TestCase
22
{
23
    // @codingStandardsIgnoreStart
24
25
    /**
26
     * Created using jwt.io
27
     */
28
    const TEST_TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtleU9uZSJ9.eyJwcm4iOiJqb2huIiwiaXNzIjoiaHR0cDovL2FwaS5zZXJ2ZXIxLmNvbS9vYXV0aDIvdG9rZW4ifQ._jXjAWMzwwG1v5N3ZOEUoLGSINtmwLsvQdfYkYAcWiY';
29
30
    const JKEY_CLASS = 'KleijnWeb\JwtBundle\Authenticator\JwtKey';
31
32
    /**
33
     * @var array
34
     */
35
    private static $keyConfig = [
36
        'keyOne' =>
37
            [
38
                'issuer' => 'http://api.server1.com/oauth2/token',
39
                'secret' => 'A Pre-Shared Key',
40
                'type'   => 'HS256',
41
            ],
42
        'keyTwo' =>
43
            [
44
                'issuer' => 'http://api.server2.com/oauth2/token',
45
                'type'   => 'RS256',
46
                'secret' => 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0F',
47
            ],
48
    ];
49
50
    // @codingStandardsIgnoreEnd
51
52
    /**
53
     * @var JwtKey[]
54
     */
55
    private $keys = [];
56
57
    protected function setUp()
58
    {
59
        foreach (self::$keyConfig as $keyId => $config) {
60
            $config['kid']      = $keyId;
61
            $this->keys[$keyId] = new JwtKey($config);
62
        }
63
    }
64
65
    /**
66
     * @test
67
     */
68
    public function getGetKeysUsingIndexesInConfig()
69
    {
70
        $authenticator = new Authenticator($this->keys);
71
72
        $this->assertInstanceOf(self::JKEY_CLASS, $authenticator->getKeyById('keyOne'));
73
        $this->assertInstanceOf(self::JKEY_CLASS, $authenticator->getKeyById('keyTwo'));
74
    }
75
76
    /**
77
     * @test
78
     */
79
    public function willGetSingleKeyWhenKeyIdIsNull()
80
    {
81
        $config = $this->keys;
82
        unset($config['keyTwo']);
83
84
        $authenticator = new Authenticator($config);
85
86
        $this->assertInstanceOf(self::JKEY_CLASS, $authenticator->getKeyById(null));
87
    }
88
89
    /**
90
     * @test
91
     * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationException
92
     */
93
    public function willFailWhenTryingToGetKeyWithoutIdWhenThereAreMoreThanOne()
94
    {
95
        $authenticator = new Authenticator($this->keys);
96
97
        $this->assertInstanceOf(self::JKEY_CLASS, $authenticator->getKeyById(null));
98
    }
99
100
    /**
101
     * @test
102
     * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationException
103
     */
104
    public function willFailWhenTryingToGetUnknownKey()
105
    {
106
        $authenticator = new Authenticator($this->keys);
107
108
        $this->assertInstanceOf(self::JKEY_CLASS, $authenticator->getKeyById('blah'));
109
    }
110
111
    /**
112
     * @test
113
     */
114
    public function authenticateTokenWillSetUserFetchedFromUserProviderOnToken()
115
    {
116
        $jwtToken      = $this->createToken(['sub' => 'john']);
117
        $authenticator = new Authenticator($this->keys);
118
        $anonToken     = new PreAuthenticatedToken('foo', $jwtToken, 'myprovider');
119
120
        $userProvider = $this->getMockBuilder(
121
            'Symfony\Component\Security\Core\User\UserProviderInterface'
122
        )->getMockForAbstractClass();
123
124
        $userProvider->expects($this->once())
125
            ->method('loadUserByUsername')
126
            ->with('john')
127
            ->willReturn(new User('john', 'hi there'));
128
129
        $authenticator->authenticateToken($anonToken, $userProvider, 'myprovider');
130
    }
131
132
    /**
133
     * @test
134
     * @expectedException \UnexpectedValueException
135
     */
136 View Code Duplication
    public function authenticateTokenWillFailIfCredentialsAreNotJwtToken()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
137
    {
138
        $authenticator = new Authenticator($this->keys);
139
        $anonToken     = new PreAuthenticatedToken('foo', ['sub' => 'john'], 'myprovider');
140
141
        $userProvider = $this->getMockBuilder(
142
            'Symfony\Component\Security\Core\User\UserProviderInterface'
143
        )->getMockForAbstractClass();
144
145
        $authenticator->authenticateToken($anonToken, $userProvider, 'myprovider');
146
    }
147
148
    /**
149
     * @test
150
     */
151 View Code Duplication
    public function supportsPreAuthToken()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
152
    {
153
        $authenticator = new Authenticator($this->keys);
154
155
        $securityToken = new PreAuthenticatedToken('foo', 'bar', 'myprovider');
156
        $actual        = $authenticator->supportsToken($securityToken, 'myprovider');
157
        $this->assertTrue($actual);
158
    }
159
160
    /**
161
     * @test
162
     * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
163
     */
164
    public function willFailWhenApiKeyNotFoundInHeader()
165
    {
166
        $authenticator = new Authenticator($this->keys);
167
        $request       = new Request();
168
        $authenticator->createToken($request, 'myprovider');
169
    }
170
171
    /**
172
     * @test
173
     */
174
    public function canGetAnonTokenWithClaims()
175
    {
176
        $authenticator = new Authenticator($this->keys);
177
        $request       = new Request();
178
        $request->headers->set('Authorization', 'Bearer ' . self::TEST_TOKEN);
179
        $token = $authenticator->createToken($request, 'myprovider');
180
181
        $expected = new JwtToken(self::TEST_TOKEN);
182
        $this->assertEquals($expected, $token->getCredentials());
183
    }
184
185
    /**
186
     * @test
187
     */
188 View Code Duplication
    public function willAddRolesFromAudienceClaimsInToken()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
189
    {
190
        $authenticator = new Authenticator($this->keys);
191
        $token         = $this->createToken(['aud' => 'guests']);
192
        $user          = $this->getMockBuilder(
193
            UserInterface::class
194
        )->getMockForAbstractClass();
195
        $token         = new PreAuthenticatedToken($user, $token, 'providerkey');
196
197
        $user->expects($this->once())
198
            ->method('addRole')
199
            ->with('guests');
200
201
        $authenticator->setUserRolesFromAudienceClaims($user, $token);
202
    }
203
204
    /**
205
     * @test
206
     */
207 View Code Duplication
    public function willAddMultipleRolesFromAudienceClaimsInToken()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
208
    {
209
        $authenticator = new Authenticator($this->keys);
210
        $token         = $this->createToken(['aud' => ['guests', 'users']]);
211
        $user          = $this->getMockBuilder(
212
            UserInterface::class
213
        )->getMockForAbstractClass();
214
215
        $token         = new PreAuthenticatedToken($user, $token, 'providerkey');
216
217
        $user->expects($this->exactly(2))
218
            ->method('addRole');
219
220
        $authenticator->setUserRolesFromAudienceClaims($user, $token);
221
    }
222
223
    /**
224
     * @param array $claims
225
     *
226
     * @return JwtToken
227
     */
228
    private function createToken(array $claims)
229
    {
230
        return new JwtToken([
231
            'header' => [
232
                'alg' => 'HS256',
233
                'typ' => 'JWT',
234
                'kid' => 'keyOne'
235
            ],
236
            'claims' => $claims,
237
            'secret' => 'secret'
238
        ]);
239
    }
240
}
241