Completed
Push — master ( d5bbb9...ab4758 )
by Milos
04:50 queued 02:32
created

Security/Http/SamlSpAuthenticationListenerTest.php (7 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace AerialShip\SamlSPBundle\Tests\Security\Http;
4
5
use AerialShip\LightSaml\Model\Assertion\Attribute;
6
use AerialShip\LightSaml\Model\Assertion\AuthnStatement;
7
use AerialShip\LightSaml\Model\Assertion\NameID;
8
use AerialShip\SamlSPBundle\Bridge\SamlSpInfo;
9
use AerialShip\SamlSPBundle\RelyingParty\RelyingPartyInterface;
10
use AerialShip\SamlSPBundle\Security\Core\Authentication\Token\SamlSpToken;
11
use AerialShip\SamlSPBundle\Security\Http\Firewall\SamlSpAuthenticationListener;
12
use Symfony\Component\HttpFoundation\ParameterBag;
13
use Symfony\Component\HttpFoundation\RedirectResponse;
14
use Symfony\Component\HttpFoundation\Request;
15
use Symfony\Component\HttpFoundation\Response;
16
use Symfony\Component\HttpFoundation\Session\SessionInterface;
17
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
18
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
19
use Symfony\Component\Security\Core\SecurityContextInterface;
20
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
21
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
22
use Symfony\Component\Security\Http\HttpUtils;
23
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
24
25
class SamlSpAuthenticationListenerTest extends \PHPUnit_Framework_TestCase
26
{
27
28
    /**
29
     * @test
30
     */
31
    public function shouldBeConstructedWithRequiredSetOfArguments()
32
    {
33
        new SamlSpAuthenticationListener(
34
            $this->createSecurityContextMock(),
35
            $this->createAuthenticationManagerMock(),
36
            $this->createSessionAuthenticationStrategyMock(),
37
            $this->createHttpUtilsMock(),
38
            'providerKey',
39
            $this->createAuthenticationSuccessHandlerMock(),
40
            $this->createAuthenticationFailureHandlerMock(),
41
            $options = array()
42
        );
43
    }
44
45
    /**
46
     * @test
47
     * @expectedException \AerialShip\SamlSPBundle\Error\RelyingPartyNotSetException
48
     */
49
    public function throwIfRelyingPartyNotSet()
50
    {
51
        $requestMock = $this->createRequestStub(
52
            $hasSessionReturn = true,
53
            $hasPreviousSessionReturn = true,
54
            $duplicatedRequestMock = $this->createRequestMock()
55
        );
56
        $duplicatedRequestMock->attributes = new ParameterBag();
57
58
        $eventMock = $this->createGetResponseEventStub($requestMock);
59
60
        $listener = new SamlSpAuthenticationListener(
61
            $this->createSecurityContextMock(),
62
            $this->createAuthenticationManagerMock(),
63
            $this->createSessionAuthenticationStrategyMock(),
64
            $this->createHttpUtilsMock(),
65
            'providerKey',
66
            $this->createAuthenticationSuccessHandlerMock(),
67
            $this->createAuthenticationFailureHandlerMock(),
68
            $options = array('require_previous_session'=>false)
69
        );
70
71
        $listener->handle($eventMock);
72
    }
73
74
75
76
    /**
77
     * @test
78
     */
79
    public function shouldDuplicateRequestAndPassItToRelyingPartyManageMethod()
80
    {
81
        $requestMock = $this->createRequestStub(
82
            $hasSessionReturn = true,
83
            $hasPreviousSessionReturn = true,
84
            $duplicatedRequestMock = $this->createRequestMock()
85
        );
86
        $duplicatedRequestMock->attributes = new ParameterBag();
87
88
        $relyingPartyMock = $this->createRelyingPartyMock();
89
        $relyingPartyMock
0 ignored issues
show
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in AerialShip\SamlSPBundle\...y\RelyingPartyInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
90
                ->expects($this->any())
91
                ->method('supports')
92
                ->will($this->returnValue(true))
93
        ;
94
        $relyingPartyMock
95
                ->expects($this->once())
96
                ->method('manage')
97
                ->with($this->equalTo($duplicatedRequestMock))
98
                ->will($this->returnValue(new RedirectResponse('http://example.com/saml/idp')))
99
        ;
100
101
        $eventMock = $this->createGetResponseEventStub($requestMock);
102
103
        $listener = new SamlSpAuthenticationListener(
104
            $this->createSecurityContextMock(),
105
            $this->createAuthenticationManagerMock(),
106
            $this->createSessionAuthenticationStrategyMock(),
107
            $this->createHttpUtilsStub($checkRequestPathReturn = true),
108
            'providerKey',
109
            $this->createAuthenticationSuccessHandlerMock(),
110
            $this->createAuthenticationFailureHandlerMock(),
111
            $options = array('require_previous_session'=>false)
112
        );
113
114
        $listener->setRelyingParty($relyingPartyMock);
115
116
        $listener->handle($eventMock);
117
    }
118
119
120
    /**
121
     * @test
122
     */
123
    public function shouldAddOptionsToDuplicatedRequest()
124
    {
125
        $requestOptions = array(
126
            'login_path' => '/saml/sp/login',
127
            'check_path' => '/saml/sp/check',
128
            'logout_path' => '/saml/sp/logout',
129
            'metadata_path' => '/saml/sp/FederationMetadata.xml',
130
            'discovery_path' => '/saml/sp/discovery',
131
            'failure_path' => 'saml/sp/failure'
132
        );
133
134
        $duplicatedRequestMock = $this->createRequestMock();
135
        $duplicatedRequestMock->attributes = new ParameterBag();
136
137
        $requestMock = $this->createRequestStub(
138
            $hasSessionReturn = true,
139
            $hasPreviousSessionReturn = true,
140
            $duplicateReturn = $duplicatedRequestMock
141
        );
142
143
        $relyingPartyMock = $this->createRelyingPartyStub(
144
            $supportsReturn = true,
145
            $manageReturn = new RedirectResponse('http://example.com/saml/idp')
146
        );
147
148
        $eventMock = $this->createGetResponseEventStub($requestMock);
149
150
        $listener = new SamlSpAuthenticationListener(
151
            $this->createSecurityContextMock(),
152
            $this->createAuthenticationManagerMock(),
153
            $this->createSessionAuthenticationStrategyMock(),
154
            $this->createHttpUtilsStub($checkRequestPathReturn = true),
155
            'providerKey',
156
            $this->createAuthenticationSuccessHandlerMock(),
157
            $this->createAuthenticationFailureHandlerMock(),
158
            $options = array_merge(array('require_previous_session'=>false), $requestOptions)
159
        );
160
161
        $listener->setRelyingParty($relyingPartyMock);
162
163
        $listener->handle($eventMock);
164
165
        $this->assertSame(
166
            $requestOptions,
167
            $duplicatedRequestMock->attributes->all()
168
        );
169
    }
170
171
172
    /**
173
     * @test
174
     */
175
    public function shouldCreateTokenFromIDPResponseAndPassItToAuthenticationManager()
176
    {
177
        $requestMock = $this->createRequestStub(
178
            $hasSessionReturn = true,
179
            $hasPreviousSessionReturn = true,
180
            $duplicateReturn = $this->createRequestMock(),
181
            $getSessionReturn = $this->createSessionMock()
182
        );
183
        $duplicateReturn->attributes = new ParameterBag();
184
185
        $nameID = new NameID();
186
        $nameID->setValue('name.id');
187
        $attribute1 = new Attribute();
188
        $attribute1->setName('common.name');
189
        $attribute1->setValues(array('my common name'));
190
        $authnStatement = new AuthnStatement();
191
        $authnStatement->setSessionIndex('1234567890');
192
193
        $relyingPartyMock = $this->createRelyingPartyStub(
194
            $supportsReturn = true,
195
            $manageReturnSamlSpInfo = new SamlSpInfo(
196
                'idp1',
197
                $nameID,
198
                array($attribute1),
199
                $authnStatement
200
            )
201
        );
202
203
        $httpUtilsStub = $this->createHttpUtilsStub(
204
            $checkRequestPathReturn = true,
205
            $createRedirectResponseReturn = new RedirectResponse('uri')
206
        );
207
208
        $testCase = $this;
209
        $authenticationManagerMock = $this->createAuthenticationManagerMock();
210
        $authenticationManagerMock
0 ignored issues
show
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Symfony\Component\Securi...icationManagerInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
211
                ->expects($this->once())
212
                ->method('authenticate')
213
                ->with($this->isInstanceOf('AerialShip\SamlSPBundle\Security\Core\Authentication\Token\SamlSpToken'))
214
                ->will($this->returnCallback(function (SamlSpToken $actualToken) use ($testCase, $manageReturnSamlSpInfo) {
215
                    $samlInfo = $actualToken->getSamlSpInfo();
216
                    $testCase->assertNotNull($samlInfo);
217
                    $testCase->assertNotNull($samlInfo->getNameID());
218
                    $testCase->assertEquals('name.id', $samlInfo->getNameID()->getValue());
219
                    $testCase->assertNotNull($samlInfo->getAttributes());
220
                    $testCase->assertCount(1, $samlInfo->getAttributes());
221
                    $testCase->assertEquals($manageReturnSamlSpInfo, $actualToken->getSamlSpInfo());
222
                    return $actualToken;
223
                }))
224
        ;
225
226
        $eventMock = $this->createGetResponseEventStub($requestMock);
227
228
        $listener = new SamlSpAuthenticationListener(
229
            $this->createSecurityContextMock(),
230
            $authenticationManagerMock,
231
            $this->createSessionAuthenticationStrategyMock(),
232
            $httpUtilsStub,
233
            'providerKey',
234
            $this->createAuthenticationSuccessHandlerStub(),
235
            $this->createAuthenticationFailureHandlerMock(),
236
            $options = array()
237
        );
238
239
        $listener->setRelyingParty($relyingPartyMock);
240
241
        $listener->handle($eventMock);
242
    }
243
244
245
    /**
246
     * @return \PHPUnit_Framework_MockObject_MockObject|Request
247
     */
248
    private function createRequestMock()
249
    {
250
        return $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false);
251
    }
252
253
    /**
254
     * @param bool $hasSessionReturn
255
     * @param bool $hasPreviousSession
256
     * @param mixed $duplicateReturn
257
     * @param mixed $getSessionReturn
258
     * @return \PHPUnit_Framework_MockObject_MockObject|Request
259
     */
260
    private function createRequestStub($hasSessionReturn = null, $hasPreviousSession = null, $duplicateReturn = null, $getSessionReturn = null)
261
    {
262
        $requestMock = $this->createRequestMock();
263
264
        $requestMock
0 ignored issues
show
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Symfony\Component\HttpFoundation\Request.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
265
                ->expects($this->any())
266
                ->method('hasSession')
267
                ->will($this->returnValue($hasSessionReturn))
268
        ;
269
        $requestMock
270
                ->expects($this->any())
271
                ->method('hasPreviousSession')
272
                ->will($this->returnValue($hasPreviousSession))
273
        ;
274
        $requestMock
275
                ->expects($this->any())
276
                ->method('duplicate')
277
                ->will($this->returnValue($duplicateReturn))
278
        ;
279
        $requestMock
280
                ->expects($this->any())
281
                ->method('getSession')
282
                ->will($this->returnValue($getSessionReturn))
283
        ;
284
285
        return $requestMock;
286
    }
287
288
    /**
289
     * @return \PHPUnit_Framework_MockObject_MockObject|RelyingPartyInterface
290
     */
291
    private function createRelyingPartyMock()
292
    {
293
        return $this->getMock('AerialShip\SamlSPBundle\RelyingParty\RelyingPartyInterface');
294
    }
295
296
    private function createRelyingPartyStub($supportsReturn = null, $manageReturn = null)
297
    {
298
        $relyingPartyMock = $this->createRelyingPartyMock();
299
300
        $relyingPartyMock
0 ignored issues
show
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in AerialShip\SamlSPBundle\...y\RelyingPartyInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
301
                ->expects($this->any())
302
                ->method('supports')
303
                ->will($this->returnValue($supportsReturn))
304
        ;
305
        $relyingPartyMock
306
                ->expects($this->any())
307
                ->method('manage')
308
                ->will($this->returnValue($manageReturn))
309
        ;
310
311
        return $relyingPartyMock;
312
    }
313
314
    /**
315
     * @return \PHPUnit_Framework_MockObject_MockObject|GetResponseEvent
316
     */
317
    private function createGetResponseEventMock()
318
    {
319
        return $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
320
    }
321
322
    /**
323
     * @param Request|null $request
324
     * @return \PHPUnit_Framework_MockObject_MockObject|GetResponseEvent
325
     */
326
    private function createGetResponseEventStub($request = null)
327
    {
328
        $getResponseEventMock = $this->createGetResponseEventMock();
329
330
        $getResponseEventMock
0 ignored issues
show
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Symfony\Component\HttpKe...\Event\GetResponseEvent.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
331
                ->expects($this->any())
332
                ->method('getRequest')
333
                ->will($this->returnValue($request))
334
        ;
335
336
        return $getResponseEventMock;
337
    }
338
339
340
    /**
341
     * @return \PHPUnit_Framework_MockObject_MockObject|SessionInterface
342
     */
343
    private function createSessionMock()
344
    {
345
        return $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface');
346
    }
347
348
    /**
349
     * @return \PHPUnit_Framework_MockObject_MockObject|SecurityContextInterface
350
     */
351
    private function createSecurityContextMock()
352
    {
353
        return $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
354
    }
355
356
    /**
357
     * @return \PHPUnit_Framework_MockObject_MockObject|AuthenticationManagerInterface
358
     */
359
    private function createAuthenticationManagerMock()
360
    {
361
        return $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
362
    }
363
364
    /**
365
     * @return \PHPUnit_Framework_MockObject_MockObject|SessionAuthenticationStrategyInterface
366
     */
367
    private function createSessionAuthenticationStrategyMock()
368
    {
369
        return $this->getMock('Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface');
370
    }
371
372
    /**
373
     * @return \PHPUnit_Framework_MockObject_MockObject|HttpUtils
374
     */
375
    private function createHttpUtilsMock()
376
    {
377
        return $this->getMock('Symfony\Component\Security\Http\HttpUtils');
378
    }
379
380
    /**
381
     * @param null $checkRequestPathResult
382
     * @param null $createRedirectResponseReturn
383
     * @return \PHPUnit_Framework_MockObject_MockObject|HttpUtils
384
     */
385
    private function createHttpUtilsStub($checkRequestPathResult = null, $createRedirectResponseReturn = null)
386
    {
387
        $httpUtilsMock = $this->createHttpUtilsMock();
388
389
        $httpUtilsMock
0 ignored issues
show
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Symfony\Component\Security\Http\HttpUtils.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
390
                ->expects($this->any())
391
                ->method('checkRequestPath')
392
                ->will($this->returnValue($checkRequestPathResult))
393
        ;
394
        $httpUtilsMock
395
                ->expects($this->any())
396
                ->method('createRedirectResponse')
397
                ->will($this->returnValue($createRedirectResponseReturn))
398
        ;
399
400
        return $httpUtilsMock;
401
    }
402
403
404
    /**
405
     * @return \PHPUnit_Framework_MockObject_MockObject|AuthenticationSuccessHandlerInterface
406
     */
407
    private function createAuthenticationSuccessHandlerMock()
408
    {
409
        return $this->getMock('Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface');
410
    }
411
412
    /**
413
     * @return \PHPUnit_Framework_MockObject_MockObject|AuthenticationSuccessHandlerInterface
414
     */
415
    protected function createAuthenticationSuccessHandlerStub()
416
    {
417
        $handlerMock = $this->createAuthenticationSuccessHandlerMock();
418
419
        $handlerMock
0 ignored issues
show
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Symfony\Component\Securi...SuccessHandlerInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
420
                ->expects($this->any())
421
                ->method('onAuthenticationSuccess')
422
                ->will($this->returnValue(new Response()))
423
        ;
424
425
        return $handlerMock;
426
    }
427
428
    /**
429
     * @return \PHPUnit_Framework_MockObject_MockObject|AuthenticationFailureHandlerInterface
430
     */
431
    private function createAuthenticationFailureHandlerMock()
432
    {
433
        return $this->getMock('Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface');
434
    }
435
}
436