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

willNotAssignRolesIfUserClassHasNoAddRoleMethod()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 11
Ratio 100 %

Importance

Changes 0
Metric Value
dl 11
loc 11
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 7
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 Symfony\Component\HttpFoundation\Request;
14
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
15
use Symfony\Component\Security\Core\User\User;
16
use KleijnWeb\JwtBundle\Tests\Classes\User as RoleAssignanleUser;
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          = new RoleAssignanleUser('john', 'hi there');
193
        $token         = new PreAuthenticatedToken($user, $token, 'providerkey');
194
195
        $result = $authenticator->setUserRolesFromAudienceClaims($user, $token);
196
197
        $this->assertEquals(['guests'], $result->getRoles());
198
    }
199
200
    /**
201
     * @test
202
     */
203
    public function willAddMultipleRolesFromAudienceClaimsInToken()
204
    {
205
        $authenticator = new Authenticator($this->keys);
206
        $token         = $this->createToken(['aud' => ['guests', 'users']]);
207
        $user          = new RoleAssignanleUser('john', 'hi there');
208
        $token         = new PreAuthenticatedToken($user, $token, 'providerkey');
209
210
        $result = $authenticator->setUserRolesFromAudienceClaims($user, $token);
211
212
        $this->assertEquals(['guests','users'], $result->getRoles());
213
    }
214
215
    /**
216
     * @test
217
     */
218 View Code Duplication
    public function willNotAssignRolesIfUserClassHasNoAddRoleMethod()
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...
219
    {
220
        $authenticator = new Authenticator($this->keys);
221
        $token         = $this->createToken(['aud' => 'guests']);
222
        $user          = new User('john', 'hi there');
223
        $token         = new PreAuthenticatedToken($user, $token, 'providerkey');
224
225
        $result = $authenticator->setUserRolesFromAudienceClaims($user, $token);
226
227
        $this->assertEquals([], $result->getRoles());
228
    }
229
230
    /**
231
     * @param array $claims
232
     *
233
     * @return JwtToken
234
     */
235
    private function createToken(array $claims)
236
    {
237
        return new JwtToken([
238
            'header' => [
239
                'alg' => 'HS256',
240
                'typ' => 'JWT',
241
                'kid' => 'keyOne'
242
            ],
243
            'claims' => $claims,
244
            'secret' => 'secret'
245
        ]);
246
    }
247
}
248