Completed
Push — develop ( 705fdc...3a7ca3 )
by
unknown
10s
created

ProcessSamlAuthenticationHandler::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 17

Duplication

Lines 19
Ratio 100 %

Importance

Changes 0
Metric Value
dl 19
loc 19
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 17
nc 1
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/**
4
 * Copyright 2016 SURFnet bv
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
namespace Surfnet\StepupRa\RaBundle\Security\Authentication\Handler;
20
21
use Surfnet\SamlBundle\Monolog\SamlAuthenticationLogger;
22
use Surfnet\SamlBundle\SAML2\Response\Assertion\InResponseTo;
23
use Surfnet\StepupBundle\Service\LoaResolutionService;
24
use Surfnet\StepupRa\RaBundle\Security\Authentication\AuthenticatedSessionStateHandler;
25
use Surfnet\StepupRa\RaBundle\Security\Authentication\SamlAuthenticationStateHandler;
26
use Surfnet\StepupRa\RaBundle\Security\Authentication\SamlInteractionProvider;
27
use Surfnet\StepupRa\RaBundle\Security\Authentication\Token\SamlToken;
28
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
29
use Symfony\Component\HttpFoundation\RedirectResponse;
30
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
31
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
32
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
33
use Symfony\Component\Security\Core\Exception\AuthenticationException;
34
35
/**
36
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects) SamlResponse parsing, validation authentication and error handling
37
 *                                                 requires quite a few classes as it is fairly complex.
38
 */
39
class ProcessSamlAuthenticationHandler implements AuthenticationHandler
40
{
41
    /**
42
     * @var AuthenticationHandler
43
     */
44
    private $nextHandler;
45
46
    /**
47
     * @var TokenStorageInterface
48
     */
49
    private $tokenStorage;
50
51
    /**
52
     * @var SamlInteractionProvider
53
     */
54
    private $samlInteractionProvider;
55
56
    /**
57
     * @var SamlAuthenticationStateHandler
58
     */
59
    private $authenticationStateHandler;
60
61
    /**
62
     * @var AuthenticatedSessionStateHandler
63
     */
64
    private $authenticatedSession;
65
66
    /**
67
     * @var AuthenticationManagerInterface
68
     */
69
    private $authenticationManager;
70
71
    /**
72
     * @var LoaResolutionService
73
     */
74
    private $loaResolutionService;
75
76
    /**
77
     * @var SamlAuthenticationLogger
78
     */
79
    private $authenticationLogger;
80
81
    /**
82
     * @var EngineInterface
83
     */
84
    private $templating;
85
86 View Code Duplication
    public function __construct(
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...
87
        TokenStorageInterface $tokenStorage,
88
        SamlInteractionProvider $samlInteractionProvider,
89
        SamlAuthenticationStateHandler $authenticationStateHandler,
90
        AuthenticatedSessionStateHandler $authenticatedSession,
91
        AuthenticationManagerInterface $authenticationManager,
92
        LoaResolutionService $loaResolutionService,
93
        SamlAuthenticationLogger $authenticationLogger,
94
        EngineInterface $templating
95
    ) {
96
        $this->tokenStorage               = $tokenStorage;
97
        $this->samlInteractionProvider    = $samlInteractionProvider;
98
        $this->authenticationStateHandler = $authenticationStateHandler;
99
        $this->authenticatedSession       = $authenticatedSession;
100
        $this->authenticationManager      = $authenticationManager;
101
        $this->loaResolutionService       = $loaResolutionService;
102
        $this->authenticationLogger       = $authenticationLogger;
103
        $this->templating                 = $templating;
104
    }
105
106
    public function process(GetResponseEvent $event)
107
    {
108
        if ($this->tokenStorage->getToken() === null
109
            && $this->samlInteractionProvider->isSamlAuthenticationInitiated()
110
        ) {
111
            $expectedInResponseTo = $this->authenticationStateHandler->getRequestId();
112
            $logger               = $this->authenticationLogger->forAuthentication($expectedInResponseTo);
113
114
            $logger->notice('No authenticated user and AuthnRequest pending, attempting to process SamlResponse');
115
116
            $assertion = $this->samlInteractionProvider->processSamlResponse($event->getRequest());
117
118
            if (!InResponseTo::assertEquals($assertion, $expectedInResponseTo)) {
119
                $logger->error('Unknown or unexpected InResponseTo in SAMLResponse');
120
121
                throw new AuthenticationException('Unknown or unexpected InResponseTo in SAMLResponse');
122
            }
123
124
            $logger->notice('Successfully processed SAMLResponse, attempting to authenticate');
125
126
            $loa = $this->loaResolutionService->getLoa($assertion->getAuthnContextClassRef());
127
128
            $token            = new SamlToken($loa);
0 ignored issues
show
Bug introduced by
It seems like $loa defined by $this->loaResolutionServ...AuthnContextClassRef()) on line 126 can be null; however, Surfnet\StepupRa\RaBundl...amlToken::__construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
129
            $token->assertion = $assertion;
130
131
            $authToken = $this->authenticationManager->authenticate($token);
132
133
            $this->authenticatedSession->logAuthenticationMoment();
134
            $this->tokenStorage->setToken($authToken);
135
136
            // migrate the session to prevent session hijacking
137
            $this->authenticatedSession->migrate();
138
139
            $event->setResponse(new RedirectResponse($this->authenticatedSession->getCurrentRequestUri()));
140
141
            $logger->notice('Authentication succeeded, redirecting to original location');
142
143
            return;
144
        }
145
146
        if ($this->nextHandler) {
147
            $this->nextHandler->process($event);
148
        }
149
    }
150
151
    public function setNext(AuthenticationHandler $handler)
152
    {
153
        $this->nextHandler = $handler;
154
    }
155
}
156