Completed
Pull Request — develop (#619)
by
unknown
04:25
created

SecurityAuthenticatorTest::testCreateToken()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 37
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 37
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 26
nc 1
nop 1

1 Method

Rating   Name   Duplication   Size   Complexity  
A SecurityAuthenticatorTest::setUp() 0 9 1
1
<?php
2
/**
3
 * main checks for airlock authenticator
4
 */
5
6
namespace Graviton\SecurityBundle\Authentication;
7
8
use \Graviton\SecurityBundle\Authentication\Provider\AuthenticationProvider;
9
use \Graviton\SecurityBundle\Authentication\Provider\AuthenticationProviderDummy;
10
use \Graviton\SecurityBundle\Authentication\Strategies\CookieFieldStrategy;
11
use \Graviton\SecurityBundle\Authentication\Strategies\HeaderFieldStrategy;
12
use \Graviton\SecurityBundle\Authentication\Strategies\MultiStrategy;
13
use \Graviton\SecurityBundle\Authentication\Strategies\SameSubnetStrategy;
14
use \Graviton\SecurityBundle\Authentication\Strategies\StrategyInterface;
15
use \Graviton\SecurityBundle\Entities\AnonymousUser;
16
use \Graviton\SecurityBundle\Entities\SecurityUser;
17
use \Graviton\SecurityBundle\Entities\SubnetUser;
18
use PHPUnit\Framework\TestCase;
19
use Symfony\Component\HttpFoundation\Request;
20
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
21
use Symfony\Component\Security\Core\Exception\AuthenticationException;
22
use Symfony\Component\Security\Core\Role\Role;
23
use \Psr\Log\LoggerInterface as Logger;
24
25
/**
26
 * Class AirlockAuthenticationKeyAuthenticatorTest
27
 *
28
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
29
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
30
 * @link     http://swisscom.ch
31
 */
32
class SecurityAuthenticatorTest extends TestCase
33
{
34
    /** @var Logger logger */
35
    private $logger;
36
37
    /**
38
     * @var AuthenticationProvider
39
     */
40
    private $userProvider;
41
42
    /**
43
     * @return void
44
     */
45
    protected function setUp()
46
    {
47
        /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject logger */
48
        $this->logger = $this->getMockBuilder('\Psr\Log\LoggerInterface')
49
            ->setMethods(array('warning', 'info'))
50
            ->getMockForAbstractClass();
51
52
        $this->userProvider = new AuthenticationProviderDummy();
53
    }
54
55
    /**
56
     * Test all auth methods for Multi Authentication
57
     *
58
     * @covers MultiStrategy::addStrategy()
59
     * @covers SecurityAuthenticator::createToken()
60
     * @covers SecurityAuthenticator::authenticateToken()
61
     *
62
     * @return void
63
     */
64
    public function testMultiAccess()
65
    {
66
        $userName = 'testUsername';
67
68
        /**
69
         * First is Auth start and second once validated
70
         * @var PreAuthenticatedToken $authenticated
71
         * @var PreAuthenticatedToken $token
72
         */
73
74
        $multiStrategy = new MultiStrategy();
75
        $multiStrategy->addStrategy($this->getStrategyByName('header'));
76
        $multiStrategy->addStrategy($this->getStrategyByName('cookie'));
77
        $multiStrategy->addStrategy($this->getStrategyByName('subnet'));
78
79
        $authenticator = new SecurityAuthenticator(
80
            true,
81
            false,
82
            true,
83
            $this->userProvider,
84
            $multiStrategy,
85
            $this->logger
86
        );
87
88
        // Test Header
89
        $request = new Request();
90
        $request->headers->set('x-rest-token', $userName);
91
92
        $token = $authenticator->createToken($request, 'test-key');
93
        $authenticated = $authenticator->authenticateToken($token, $this->userProvider, 'test-key');
94
95
        $roles = $this->rolesToArray($authenticated->getRoles());
96
        // Getting the dummy user and not the real Document User.
97
        $user = $authenticated->getUser()->getUser();
98
        $this->assertEquals([SecurityUser::ROLE_CONSULTANT, SecurityUser::ROLE_USER], $roles, json_encode($roles));
99
        $this->assertEquals($userName, $user->username);
100
101
        // With header, but unknown and allowing Anonymous
102
        $request = new Request();
103
        $request->headers->set('x-rest-token', 'unknown');
104
105
        $token = $authenticator->createToken($request, 'test-key');
106
        $authenticated = $authenticator->authenticateToken($token, $this->userProvider, 'test-key');
107
108
        $roles = $this->rolesToArray($authenticated->getRoles());
109
        /** @var AnonymousUser $user */
110
        $user = $authenticated->getUser()->getUser();
111
        $this->assertEquals([SecurityUser::ROLE_ANONYMOUS, SecurityUser::ROLE_USER], $roles, json_encode($roles));
112
        $this->assertEquals('anonymous', $user->getUsername());
113
114
        // With cookie
115
        $request = new Request();
116
        $request->cookies->set('graviton_user', $userName);
117
118
        $token = $authenticator->createToken($request, 'test-key');
119
        $authenticated = $authenticator->authenticateToken($token, $this->userProvider, 'test-key');
120
121
        $roles = $this->rolesToArray($authenticated->getRoles());
122
        /** @var \stdClass $user */
123
        $user = $authenticated->getUser()->getUser();
124
        $this->assertEquals([SecurityUser::ROLE_CONSULTANT, SecurityUser::ROLE_USER], $roles, json_encode($roles));
125
        $this->assertEquals($userName, $user->username);
126
127
128
        // Test Header for Subnet
129
        $request = new Request([], [], [], [], [], ['REMOTE_ADDR' => '0.0.0.0']);
130
        $request->headers->set('graviton_subnet', $userName);
131
132
        $token = $authenticator->createToken($request, 'test-key');
133
        $authenticated = $authenticator->authenticateToken($token, $this->userProvider, 'test-key');
134
135
        $roles = $this->rolesToArray($authenticated->getRoles());
136
        // Getting the dummy user and not the real Document User.
137
        /** @var SubnetUser $user */
138
        $user = $authenticated->getUser()->getUser();
139
        $this->assertEquals([SecurityUser::ROLE_SUBNET, SecurityUser::ROLE_USER], $roles, json_encode($roles));
140
        $this->assertEquals($userName, $user->getUsername());
141
    }
142
143
    /**
144
     * Test all auth methods for Multi Authentication
145
     *
146
     * @return void
147
     */
148
    public function testHeaderAccess()
149
    {
150
        $userName = 'testUsername';
151
152
        /**
153
         * First is Auth start and second once validated
154
         * @var PreAuthenticatedToken $authenticated
155
         * @var PreAuthenticatedToken $token
156
         */
157
158
        $strategy = $this->getStrategyByName('header');
159
160
        $authenticator = new SecurityAuthenticator(
161
            false,
162
            false,
163
            true,
164
            $this->userProvider,
165
            $strategy,
166
            $this->logger
167
        );
168
169
        // Test Header
170
        $request = new Request();
171
        $request->headers->set('x-rest-token', $userName);
172
173
        $token = $authenticator->createToken($request, 'test-key');
174
        $authenticated = $authenticator->authenticateToken($token, $this->userProvider, 'test-key');
175
176
        $roles = $this->rolesToArray($authenticated->getRoles());
177
        // Getting the dummy user and not the real Document User.
178
        $user = $authenticated->getUser()->getUser();
179
        $this->assertEquals([SecurityUser::ROLE_CONSULTANT, SecurityUser::ROLE_USER], $roles, json_encode($roles));
180
        $this->assertEquals($userName, $user->username);
181
182
        // With header, but unknown and allowing Anonymous
183
        $request = new Request();
184
        $request->headers->set('x-rest-token', 'unknown');
185
186
        $token = $authenticator->createToken($request, 'test-key');
187
        $authenticated = $authenticator->authenticateToken($token, $this->userProvider, 'test-key');
188
189
        $roles = $this->rolesToArray($authenticated->getRoles());
190
        /** @var AnonymousUser $user */
191
        $user = $authenticated->getUser()->getUser();
192
        $this->assertEquals([SecurityUser::ROLE_ANONYMOUS, SecurityUser::ROLE_USER], $roles, json_encode($roles));
193
        $this->assertEquals('anonymous', $user->getUsername());
194
    }
195
196
    /**
197
     * Test without sending any auth
198
     *
199
     * @return void
200
     */
201
    public function testHeaderRequiredAccess()
202
    {
203
        $this->expectException(AuthenticationException::class);
204
205
        /**
206
         * First is Auth start and second once validated
207
         * @var PreAuthenticatedToken $authenticated
208
         * @var PreAuthenticatedToken $token
209
         */
210
211
        $strategy = $this->getStrategyByName('header');
212
213
        $authenticator = new SecurityAuthenticator(
214
            true,
215
            false,
216
            true,
217
            $this->userProvider,
218
            $strategy,
219
            $this->logger
220
        );
221
222
        // With header, but unknown and allowing Anonymous
223
        $request = new Request();
224
        $token = $authenticator->createToken($request, 'test-key');
225
        $authenticator->authenticateToken($token, $this->userProvider, 'test-key');
226
    }
227
228
    /**
229
     * Flat out roles for easier comparison. Sorted.
230
     * @param Role[] $roles Array list of Sf Roles
231
     *
232
     * @return array
233
     */
234
    private function rolesToArray($roles)
235
    {
236
        $roles = array_map(
237
            function ($role) {
238
                /** @var Role $role */
239
                return (string) $role->getRole();
240
            },
241
            $roles
242
        );
243
        sort($roles);
244
        return $roles;
245
    }
246
247
    /**
248
     * Simplified Strategy getter
249
     *
250
     * @param string $strategy Name of requested strategy
251
     * @return StrategyInterface|null
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use HeaderFieldStrategy|Cook...SameSubnetStrategy|null.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
252
     */
253
    private function getStrategyByName($strategy)
254
    {
255
        switch ($strategy) {
256
            case 'header':
257
                return new HeaderFieldStrategy('x-rest-token');
258
                break;
259
            case 'cookie':
260
                return new CookieFieldStrategy('graviton_user');
261
                break;
262
            case 'subnet':
263
                return new SameSubnetStrategy('0.0.0.0', 'graviton_subnet');
264
                break;
265
        }
266
        return null;
267
    }
268
}
269