Completed
Push — feature/tests-and-symfony-34 ( d06f89 )
by Michiel
04:18 queued 01:47
created

ConsumeAssertionService::consumeAssertion()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 35
rs 9.36
c 0
b 0
f 0
cc 3
nc 3
nop 2
1
<?php
2
3
/**
4
 * Copyright 2018 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\StepupGateway\GatewayBundle\Service\Gateway;
20
21
use Exception;
22
use Surfnet\SamlBundle\Entity\IdentityProvider;
23
use Surfnet\SamlBundle\Entity\ServiceProvider;
24
use Surfnet\SamlBundle\Http\PostBinding;
25
use Surfnet\SamlBundle\Monolog\SamlAuthenticationLogger;
26
use Surfnet\StepupGateway\GatewayBundle\Exception\ResponseFailureException;
27
use Surfnet\StepupGateway\GatewayBundle\Saml\AssertionAdapter;
28
use Surfnet\StepupGateway\GatewayBundle\Saml\Exception\UnknownInResponseToException;
29
use Surfnet\StepupGateway\GatewayBundle\Saml\ResponseContext;
30
use Symfony\Component\HttpFoundation\Request;
31
32
class ConsumeAssertionService
33
{
34
    const RESPONSE_CONTEXT_SERVICE_ID = 'gateway.proxy.response_context';
35
36
    /** @var PostBinding */
37
    private $postBinding;
38
39
    /** @var SamlAuthenticationLogger */
40
    private $samlLogger;
41
42
    /** @var ServiceProvider */
43
    private $hostedServiceProvider;
44
45
    /** @var IdentityProvider */
46
    private $remoteIdp;
47
48
    /**
49
     * GatewayServiceProviderService constructor.
50
     * @param PostBinding $postBinding
51
     * @param SamlAuthenticationLogger $samlLogger
52
     * @param ServiceProvider $hostedServiceProvider
53
     * @param IdentityProvider $remoteIdp
54
     */
55
    public function __construct(
56
        PostBinding $postBinding,
57
        SamlAuthenticationLogger $samlLogger,
58
        ServiceProvider $hostedServiceProvider,
59
        IdentityProvider $remoteIdp
60
    ) {
61
        $this->postBinding = $postBinding;
62
        $this->samlLogger = $samlLogger;
63
        $this->hostedServiceProvider = $hostedServiceProvider;
64
        $this->remoteIdp = $remoteIdp;
65
    }
66
67
    /**
68
     * Receive an AuthnResponse from an identity provider.
69
     *
70
     * The AuthnRequest started in the LoginService resulted in an AuthnResponse
71
     * from the IDP. This method handles the assertion and state. After which the
72
     * actual second factor verification can begin.
73
     *
74
     * @param Request $request
75
     * @param ResponseContext $responseContext
76
     * @return void
77
     */
78
    public function consumeAssertion(Request $request, ResponseContext $responseContext)
79
    {
80
        $originalRequestId = $responseContext->getInResponseTo();
81
82
        $logger = $this->samlLogger->forAuthentication($originalRequestId);
83
        $logger->notice('Received SAMLResponse, attempting to process for Proxy Response');
84
85
        try {
86
            $assertion = $this->postBinding->processResponse(
87
                $request,
88
                $this->remoteIdp,
89
                $this->hostedServiceProvider
90
            );
91
        } catch (Exception $exception) {
92
            $message = sprintf('Could not process received Response, error: "%s"', $exception->getMessage());
93
            $logger->error($message);
94
95
            throw new ResponseFailureException($message);
96
        }
97
98
        $adaptedAssertion = new AssertionAdapter($assertion);
99
        $expectedInResponseTo = $responseContext->getExpectedInResponseTo();
100
        if (!$adaptedAssertion->inResponseToMatches($expectedInResponseTo)) {
101
            throw new UnknownInResponseToException(
102
                $adaptedAssertion->getInResponseTo(),
103
                $expectedInResponseTo
104
            );
105
        }
106
107
        $logger->notice('Successfully processed SAMLResponse');
108
109
        $responseContext->saveAssertion($assertion);
110
111
        $logger->notice(sprintf('Forwarding to second factor controller for loa determination and handling'));
112
    }
113
}
114