Completed
Push — master ( ee280a...529931 )
by John
01:02 queued 57s
created

AuthenticatorTest::supportsPreAuthToken()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 8
Ratio 100 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 8
loc 8
rs 9.4285
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 Symfony\Component\HttpFoundation\Request;
14
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
15
use Symfony\Component\Security\Core\User\User;
16
17
/**
18
 * @author John Kleijn <[email protected]>
19
 */
20
class AuthenticatorTest extends \PHPUnit_Framework_TestCase
21
{
22
    // @codingStandardsIgnoreStart
23
24
    /**
25
     * Created using jwt.io
26
     */
27
    const TEST_TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtleU9uZSJ9.eyJwcm4iOiJqb2huIiwiaXNzIjoiaHR0cDovL2FwaS5zZXJ2ZXIxLmNvbS9vYXV0aDIvdG9rZW4ifQ._jXjAWMzwwG1v5N3ZOEUoLGSINtmwLsvQdfYkYAcWiY';
28
29
    const JKEY_CLASS = 'KleijnWeb\JwtBundle\Authenticator\JwtKey';
30
31
    /**
32
     * @var array
33
     */
34
    private static $keyConfig = [
35
        'keyOne' =>
36
            [
37
                'issuer' => 'http://api.server1.com/oauth2/token',
38
                'secret' => 'A Pre-Shared Key',
39
                'type'   => 'HS256',
40
            ],
41
        'keyTwo' =>
42
            [
43
                'issuer' => 'http://api.server2.com/oauth2/token',
44
                'type'   => 'RS256',
45
                'secret' => 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0F',
46
            ],
47
    ];
48
49
    // @codingStandardsIgnoreEnd
50
51
    /**
52
     * @var JwtKey[]
53
     */
54
    private $keys = [];
55
56
    protected function setUp()
57
    {
58
        foreach (self::$keyConfig as $keyId => $config) {
59
            $config['kid']      = $keyId;
60
            $this->keys[$keyId] = new JwtKey($config);
61
        }
62
    }
63
64
    /**
65
     * @test
66
     */
67
    public function getGetKeysUsingIndexesInConfig()
68
    {
69
        $authenticator = new Authenticator($this->keys);
70
71
        $this->assertInstanceOf(self::JKEY_CLASS, $authenticator->getKeyById('keyOne'));
72
        $this->assertInstanceOf(self::JKEY_CLASS, $authenticator->getKeyById('keyTwo'));
73
    }
74
75
    /**
76
     * @test
77
     */
78
    public function willGetSingleKeyWhenKeyIdIsNull()
79
    {
80
        $config = $this->keys;
81
        unset($config['keyTwo']);
82
83
        $authenticator = new Authenticator($config);
84
85
        $this->assertInstanceOf(self::JKEY_CLASS, $authenticator->getKeyById(null));
86
    }
87
88
    /**
89
     * @test
90
     * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationException
91
     */
92
    public function willFailWhenTryingToGetKeyWithoutIdWhenThereAreMoreThanOne()
93
    {
94
        $authenticator = new Authenticator($this->keys);
95
96
        $this->assertInstanceOf(self::JKEY_CLASS, $authenticator->getKeyById(null));
97
    }
98
99
    /**
100
     * @test
101
     * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationException
102
     */
103
    public function willFailWhenTryingToGetUnknownKey()
104
    {
105
        $authenticator = new Authenticator($this->keys);
106
107
        $this->assertInstanceOf(self::JKEY_CLASS, $authenticator->getKeyById('blah'));
108
    }
109
110
    /**
111
     * @test
112
     */
113
    public function authenticateTokenWillSetUserFetchedFromUserProviderOnToken()
114
    {
115
        $jwtToken      = $this->createToken(['sub' => 'john']);
116
        $authenticator = new Authenticator($this->keys);
117
        $anonToken     = new PreAuthenticatedToken('foo', $jwtToken, 'myprovider');
118
119
        $userProvider = $this->getMockBuilder(
120
            'Symfony\Component\Security\Core\User\UserProviderInterface'
121
        )->getMockForAbstractClass();
122
123
        $userProvider->expects($this->once())
124
            ->method('loadUserByUsername')
125
            ->with('john')
126
            ->willReturn(new User('john', 'hi there'));
127
128
        $authenticator->authenticateToken($anonToken, $userProvider, 'myprovider');
129
    }
130
131
    /**
132
     * @test
133
     * @expectedException \UnexpectedValueException
134
     */
135 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...
136
    {
137
        $authenticator = new Authenticator($this->keys);
138
        $anonToken     = new PreAuthenticatedToken('foo', ['sub' => 'john'], 'myprovider');
139
140
        $userProvider = $this->getMockBuilder(
141
            'Symfony\Component\Security\Core\User\UserProviderInterface'
142
        )->getMockForAbstractClass();
143
144
        $authenticator->authenticateToken($anonToken, $userProvider, 'myprovider');
145
    }
146
147
    /**
148
     * @test
149
     */
150 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...
151
    {
152
        $authenticator = new Authenticator($this->keys);
153
154
        $securityToken = new PreAuthenticatedToken('foo', 'bar', 'myprovider');
155
        $actual        = $authenticator->supportsToken($securityToken, 'myprovider');
156
        $this->assertTrue($actual);
157
    }
158
159
    /**
160
     * @test
161
     * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
162
     */
163
    public function willFailWhenApiKeyNotFoundInHeader()
164
    {
165
        $authenticator = new Authenticator($this->keys);
166
        $request       = new Request();
167
        $authenticator->createToken($request, 'myprovider');
168
    }
169
170
    /**
171
     * @test
172
     */
173
    public function canGetAnonTokenWithClaims()
174
    {
175
        $authenticator = new Authenticator($this->keys);
176
        $request       = new Request();
177
        $request->headers->set('Authorization', 'Bearer ' . self::TEST_TOKEN);
178
        $token = $authenticator->createToken($request, 'myprovider');
179
180
        $expected = new JwtToken(self::TEST_TOKEN);
181
        $this->assertEquals($expected, $token->getCredentials());
182
    }
183
184
    /**
185
     * @param array $claims
186
     *
187
     * @return JwtToken
188
     */
189
    private function createToken(array $claims)
190
    {
191
        return new JwtToken([
192
            'header' => [
193
                'alg' => 'HS256',
194
                'typ' => 'JWT',
195
                'kid' => 'keyOne'
196
            ],
197
            'claims' => $claims,
198
            'secret' => 'secret'
199
        ]);
200
    }
201
}
202