Completed
Push — feature/auth-multi-strategy-co... ( 0e8a44 )
by
unknown
63:21
created

SecurityAuthenticatorTest::stringProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 10
Ratio 100 %

Importance

Changes 0
Metric Value
dl 10
loc 10
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 7
nc 1
nop 0
1
<?php
2
/**
3
 * main checks for airlock authenticator
4
 */
5
6
namespace Graviton\SecurityBundle\Authentication;
7
8
use Documents\User;
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 Symfony\Component\HttpFoundation\Request;
19
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
20
use Symfony\Component\Security\Core\Exception\AuthenticationException;
21
use Symfony\Component\Security\Core\Role\Role;
22
23
/**
24
 * Class AirlockAuthenticationKeyAuthenticatorTest
25
 *
26
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
27
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
28
 * @link     http://swisscom.ch
29
 */
30
class SecurityAuthenticatorTest extends \PHPUnit_Framework_TestCase
31
{
32
    /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject logger */
33
    private $logger;
34
35
    /**
36
     * @var \Graviton\SecurityBundle\Authentication\Provider\AuthenticationProvider
37
     */
38
    private $userProvider;
39
40
    /**
41
     * @return void
42
     */
43
    protected function setUp()
44
    {
45
        /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject logger */
46
        $this->logger = $this->getMockBuilder('\Psr\Log\LoggerInterface')
47
            ->setMethods(array('warning', 'info'))
48
            ->getMockForAbstractClass();
49
50
        $this->userProvider = new AuthenticationProviderDummy();
51
    }
52
53
    /**
54
     * Test all auth methods for Multi Authentication
55
     *
56
     * @covers MultiStrategy
57
     * @covers SecurityAuthenticator
58
     *
59
     * @return void
60
     */
61
    public function testMultiAccess()
62
    {
63
        $userName = 'testUsername';
64
65
        /**
66
         * First is Auth start and second once validated
67
         * @var PreAuthenticatedToken $authenticated
68
         * @var PreAuthenticatedToken $token
69
         */
70
71
        $multiStrategy = new MultiStrategy();
72
        $multiStrategy->addStrategy($this->getStrategyByName('header'));
73
        $multiStrategy->addStrategy($this->getStrategyByName('cookie'));
74
        $multiStrategy->addStrategy($this->getStrategyByName('subnet'));
75
76
        $authenticator = new SecurityAuthenticator(
77
            true,
78
            false,
79
            true,
80
            $this->userProvider,
81
            $multiStrategy,
82
            $this->logger
83
        );
84
85
        // Test Header
86
        $request = new Request();
87
        $request->headers->set('x-rest-token', $userName);
88
89
        $token = $authenticator->createToken($request, 'test-key');
90
        $authenticated = $authenticator->authenticateToken($token, $this->userProvider, 'test-key');
91
92
        $roles = $this->rolesToArray($authenticated->getRoles());
93
        // Getting the dummy user and not the real Document User.
94
        $user = $authenticated->getUser()->getUser();
95
        $this->assertEquals([SecurityUser::ROLE_CONSULTANT, SecurityUser::ROLE_USER], $roles, json_encode($roles));
96
        $this->assertEquals($userName, $user->username);
97
98
        // With header, but unknown and allowing Anonymous
99
        $request = new Request();
100
        $request->headers->set('x-rest-token', 'unknown');
101
102
        $token = $authenticator->createToken($request, 'test-key');
103
        $authenticated = $authenticator->authenticateToken($token, $this->userProvider, 'test-key');
104
105
        $roles = $this->rolesToArray($authenticated->getRoles());
106
        /** @var AnonymousUser $user */
107
        $user = $authenticated->getUser()->getUser();
108
        $this->assertEquals([SecurityUser::ROLE_ANONYMOUS, SecurityUser::ROLE_USER], $roles, json_encode($roles));
109
        $this->assertEquals('anonymous', $user->getUsername());
110
111
        // With cookie
112
        $request = new Request();
113
        $request->cookies->set('graviton_user', $userName);
114
115
        $token = $authenticator->createToken($request, 'test-key');
116
        $authenticated = $authenticator->authenticateToken($token, $this->userProvider, 'test-key');
117
118
        $roles = $this->rolesToArray($authenticated->getRoles());
119
        /** @var \stdClass $user */
120
        $user = $authenticated->getUser()->getUser();
121
        $this->assertEquals([SecurityUser::ROLE_CONSULTANT, SecurityUser::ROLE_USER], $roles, json_encode($roles));
122
        $this->assertEquals($userName, $user->username);
123
124
125
        // Test Header for Subnet
126
        $request = new Request([], [], [], [], [], ['REMOTE_ADDR' => '0.0.0.0']);
127
        $request->headers->set('graviton_subnet', $userName);
128
129
        $token = $authenticator->createToken($request, 'test-key');
130
        $authenticated = $authenticator->authenticateToken($token, $this->userProvider, 'test-key');
131
132
        $roles = $this->rolesToArray($authenticated->getRoles());
133
        // Getting the dummy user and not the real Document User.
134
        /** @var SubnetUser $user */
135
        $user = $authenticated->getUser()->getUser();
136
        $this->assertEquals([SecurityUser::ROLE_SUBNET, SecurityUser::ROLE_USER], $roles, json_encode($roles));
137
        $this->assertEquals($userName, $user->getUsername());
138
    }
139
140
    /**
141
     * Test all auth methods for Multi Authentication
142
     *
143
     * @covers HeaderFieldStrategy
144
     * @covers SecurityAuthenticator
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
     * @covers HeaderFieldStrategy
200
     * @covers SecurityAuthenticator
201
     *
202
     * @return void
203
     */
204
    public function testHeaderRequiredAccess()
205
    {
206
        $this->expectException(AuthenticationException::class);
207
208
        /**
209
         * First is Auth start and second once validated
210
         * @var PreAuthenticatedToken $authenticated
211
         * @var PreAuthenticatedToken $token
212
         */
213
214
        $strategy = $this->getStrategyByName('header');
215
216
        $authenticator = new SecurityAuthenticator(
217
            true,
218
            false,
219
            true,
220
            $this->userProvider,
221
            $strategy,
222
            $this->logger
223
        );
224
225
        // With header, but unknown and allowing Anonymous
226
        $request = new Request();
227
        $token = $authenticator->createToken($request, 'test-key');
228
        $authenticated = $authenticator->authenticateToken($token, $this->userProvider, 'test-key');
229
    }
230
231
    /**
232
     * Flat out roles for easier comparison. Sorted.
233
     * @param Role[] $roles Array list of Sf Roles
234
     *
235
     * @return array
236
     */
237
    private function rolesToArray($roles)
238
    {
239
        $roles = array_map(
240
            function ($role) {
241
                /** @var Role $role */
242
                return (string) $role->getRole();
243
            },
244
            $roles
245
        );
246
        sort($roles);
247
        return $roles;
248
    }
249
250
    /**
251
     * Simplified Strategy getter
252
     *
253
     * @param string $strategy Name of requested strategy
254
     * @return StrategyInterface|null
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use HeaderFieldStrategy|null...tegy|SameSubnetStrategy.

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...
255
     */
256
    private function getStrategyByName($strategy)
257
    {
258
        switch ($strategy) {
259
            case 'header':
260
                return new HeaderFieldStrategy('x-rest-token');
261
                break;
262
            case 'cookie':
263
                return new CookieFieldStrategy('graviton_user');
264
                break;
265
            case 'subnet':
266
                return new SameSubnetStrategy('0.0.0.0', 'graviton_subnet');
267
                break;
268
        }
269
    }
270
}
271