LogoutReceiveResponse   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 121
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 14

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 16
c 4
b 0
f 0
lcom 1
cbo 14
dl 0
loc 121
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 1
A supports() 0 10 3
A manage() 0 12 2
A getLogoutResponse() 0 10 3
A validateRequestState() 0 11 3
A deleteSSOSession() 0 13 4
1
<?php
2
3
namespace AerialShip\SamlSPBundle\Bridge;
4
5
use AerialShip\LightSaml\Model\Protocol\LogoutResponse;
6
use AerialShip\SamlSPBundle\Config\ServiceInfoCollection;
7
use AerialShip\SamlSPBundle\RelyingParty\RelyingPartyInterface;
8
use AerialShip\SamlSPBundle\Security\Core\Authentication\Token\SamlSpToken;
9
use AerialShip\SamlSPBundle\State\Request\RequestStateStoreInterface;
10
use AerialShip\SamlSPBundle\State\SSO\SSOStateStoreInterface;
11
use Symfony\Component\HttpFoundation\Request;
12
use Symfony\Component\Security\Core\SecurityContextInterface;
13
use Symfony\Component\Security\Http\HttpUtils;
14
15
class LogoutReceiveResponse extends LogoutBase implements RelyingPartyInterface
16
{
17
    /** @var BindingManager */
18
    protected $bindingManager;
19
20
    /** @var RequestStateStoreInterface  */
21
    protected $requestStore;
22
23
    /** @var ServiceInfoCollection  */
24
    protected $serviceInfoCollection;
25
26
    /** @var \Symfony\Component\Security\Core\SecurityContextInterface  */
27
    protected $securityContext;
28
29
30
    /**
31
     * @param BindingManager $bindingManager
32
     * @param RequestStateStoreInterface $requestStore
33
     * @param \AerialShip\SamlSPBundle\Config\ServiceInfoCollection $serviceInfoCollection
34
     * @param \AerialShip\SamlSPBundle\State\SSO\SSOStateStoreInterface $ssoStore
35
     * @param \Symfony\Component\Security\Core\SecurityContextInterface $securityContext
36
     * @param \Symfony\Component\Security\Http\HttpUtils $httpUtils
37
     */
38
    public function __construct(
39
        BindingManager $bindingManager,
40
        RequestStateStoreInterface $requestStore,
41
        ServiceInfoCollection $serviceInfoCollection,
42
        SSOStateStoreInterface $ssoStore,
43
        SecurityContextInterface $securityContext,
44
        HttpUtils $httpUtils
45
    ) {
46
        parent::__construct($ssoStore, $httpUtils);
47
        $this->bindingManager = $bindingManager;
48
        $this->requestStore = $requestStore;
49
        $this->serviceInfoCollection = $serviceInfoCollection;
50
        $this->securityContext = $securityContext;
51
    }
52
53
54
    /**
55
     * @param \Symfony\Component\HttpFoundation\Request $request
56
     * @return bool
57
     */
58
    public function supports(Request $request)
59
    {
60
        if ($request->attributes->get('logout_path') != $request->getPathInfo()) {
61
            return false;
62
        }
63
        if (!$request->get('SAMLResponse')) {
64
            return false;
65
        }
66
        return true;
67
    }
68
69
    /**
70
     * @param \Symfony\Component\HttpFoundation\Request $request
71
     * @throws \RuntimeException
72
     * @throws \InvalidArgumentException if cannot manage the Request
73
     * @return \Symfony\Component\HttpFoundation\Response|SamlSpInfo|null
74
     */
75
    public function manage(Request $request)
76
    {
77
        if (!$this->supports($request)) {
78
            throw new \InvalidArgumentException('Unsupported request');
79
        }
80
81
        $logoutResponse = $this->getLogoutResponse($request);
82
        $this->validateRequestState($logoutResponse);
83
        $this->deleteSSOSession($logoutResponse);
84
85
        return $this->httpUtils->createRedirectResponse($request, $request->attributes->get('local_logout_path'));
86
    }
87
88
89
    /**
90
     * @param Request $request
91
     * @return LogoutResponse
92
     * @throws \InvalidArgumentException
93
     */
94
    protected function getLogoutResponse(Request $request)
95
    {
96
        /** @var  $logoutResponse LogoutResponse */
97
        $logoutResponse = $this->bindingManager->receive($request);
98
        if (!$logoutResponse || !$logoutResponse instanceof LogoutResponse) {
99
            throw new \InvalidArgumentException('Did not receive logout response');
100
        }
101
102
        return $logoutResponse;
103
    }
104
105
    /**
106
     * @param LogoutResponse $logoutResponse
107
     * @throws \RuntimeException
108
     */
109
    protected function validateRequestState(LogoutResponse $logoutResponse)
110
    {
111
        $state = $this->requestStore->get($logoutResponse->getInResponseTo());
112
        if (!$state) {
113
            throw new \RuntimeException('Got response to a request that was not made');
114
        }
115
        if ($state->getDestination() != $logoutResponse->getIssuer()) {
116
            throw new \RuntimeException('Got response from different issuer');
117
        }
118
        $this->requestStore->remove($state);
119
    }
120
121
122
    protected function deleteSSOSession(LogoutResponse $logoutResponse)
123
    {
124
        $serviceInfo = $this->serviceInfoCollection->findByIDPEntityID($logoutResponse->getIssuer());
125
        /** @var $token SamlSpToken */
126
        $token = $this->securityContext->getToken();
127
        if ($token && $token instanceof SamlSpToken) {
128
            $samlInfo = $token->getSamlSpInfo();
129
            if ($samlInfo) {
130
                $arrStates = $this->getSSOState($serviceInfo, $samlInfo->getNameID()->getValue(), $samlInfo->getAuthnStatement()->getSessionIndex());
0 ignored issues
show
Bug introduced by
It seems like $serviceInfo defined by $this->serviceInfoCollec...tResponse->getIssuer()) on line 124 can be null; however, AerialShip\SamlSPBundle\...goutBase::getSSOState() 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...
131
                $this->deleteSSOState($arrStates);
132
            }
133
        }
134
    }
135
}
136