Completed
Push — bugfix/institution-based-on-sh... ( 23e8a9 )
by
unknown
02:11
created

ResponseContext::getIdentityNameId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
/**
4
 * Copyright 2014 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\Saml;
20
21
use DateTime;
22
use DateTimeZone;
23
use DOMDocument;
24
use SAML2_Assertion;
25
use Surfnet\SamlBundle\Entity\IdentityProvider;
26
use Surfnet\SamlBundle\Entity\ServiceProvider;
27
use Surfnet\StepupGateway\GatewayBundle\Entity\SecondFactor;
28
use Surfnet\StepupGateway\GatewayBundle\Saml\Proxy\ProxyStateHandler;
29
use Surfnet\StepupGateway\GatewayBundle\Service\SamlEntityService;
30
31
class ResponseContext
32
{
33
    /**
34
     * @var IdentityProvider
35
     */
36
    private $hostedIdentityProvider;
37
38
    /**
39
     * @var \Surfnet\StepupGateway\GatewayBundle\Service\SamlEntityService
40
     */
41
    private $samlEntityService;
42
43
    /**
44
     * @var ProxyStateHandler
45
     */
46
    private $stateHandler;
47
48
    /**
49
     * @var DateTime
50
     */
51
    private $generationTime;
52
53
    /**
54
     * @var IdentityProvider|null
55
     */
56
    private $authenticatingIdp;
57
58
    /**
59
     * @var ServiceProvider
60
     */
61
    private $targetServiceProvider;
62
63
    public function __construct(
64
        IdentityProvider $identityProvider,
65
        SamlEntityService $samlEntityService,
66
        ProxyStateHandler $stateHandler
67
    ) {
68
        $this->hostedIdentityProvider = $identityProvider;
69
        $this->samlEntityService      = $samlEntityService;
70
        $this->stateHandler           = $stateHandler;
71
        $this->generationTime         = new DateTime('now', new DateTimeZone('UTC'));
72
    }
73
74
    /**
75
     * @return string
76
     */
77
    public function getDestination()
78
    {
79
        $serviceProvider = $this->getServiceProvider();
80
81
        if (!$serviceProvider) {
82
            return null;
83
        }
84
85
        return $serviceProvider->getAssertionConsumerUrl();
86
    }
87
88
    /**
89
     * @return null|string
90
     */
91
    public function getIssuer()
92
    {
93
        return $this->hostedIdentityProvider->getEntityId();
94
    }
95
96
    /**
97
     * @return int
98
     */
99
    public function getIssueInstant()
100
    {
101
        return $this->generationTime->getTimestamp();
102
    }
103
104
    /**
105
     * @return null|string
106
     */
107
    public function getInResponseTo()
108
    {
109
        return $this->stateHandler->getRequestId();
110
    }
111
112
    /**
113
     * @return null|string
114
     */
115
    public function getExpectedInResponseTo()
116
    {
117
        return $this->stateHandler->getGatewayRequestId();
118
    }
119
120
    /**
121
     * @return null|string
122
     */
123
    public function getRequiredLoa()
124
    {
125
        return $this->stateHandler->getRequiredLoaIdentifier();
126
    }
127
128
    /**
129
     * @return IdentityProvider
130
     */
131
    public function getIdentityProvider()
132
    {
133
        return $this->hostedIdentityProvider;
134
    }
135
136
    /**
137
     * @return null|ServiceProvider
138
     */
139
    public function getServiceProvider()
140
    {
141
        if (isset($this->targetServiceProvider)) {
142
            return $this->targetServiceProvider;
143
        }
144
145
        $serviceProviderId = $this->stateHandler->getRequestServiceProvider();
146
147
        return $this->targetServiceProvider = $this->samlEntityService->getServiceProvider($serviceProviderId);
148
    }
149
150
    /**
151
     * @return null|string
152
     */
153
    public function getRelayState()
154
    {
155
        return $this->stateHandler->getRelayState();
156
    }
157
158
    /**
159
     * @param SAML2_Assertion $assertion
160
     */
161
    public function saveAssertion(SAML2_Assertion $assertion)
162
    {
163
        // we pluck the NameId to make it easier to access it without having to reconstitute the assertion
164
        $nameId = $assertion->getNameId();
165
        if (!empty($nameId['Value'])) {
166
            $this->stateHandler->saveIdentityNameId($nameId['Value']);
167
        }
168
169
        // same for the entityId of the authenticating Authority
170
        $authenticatingAuthorities = $assertion->getAuthenticatingAuthority();
171
        if (!empty($authenticatingAuthorities)) {
172
            $this->stateHandler->setAuthenticatingIdp(reset($authenticatingAuthorities));
173
        }
174
175
        // And also attempt to save the user's schacHomeOrganization
176
        $attributes = $assertion->getAttributes();
177
        if (array_key_exists('urn:mace:terena.org:attribute-def:schacHomeOrganization', $attributes) &&
178
            !empty($attributes['urn:mace:terena.org:attribute-def:schacHomeOrganization'])
179
        ) {
180
            $schacHomeOrganization = $attributes['urn:mace:terena.org:attribute-def:schacHomeOrganization'];
181
            $this->stateHandler->setSchacHomeOrganization(reset($schacHomeOrganization));
182
        }
183
184
        $this->stateHandler->saveAssertion($assertion->toXML()->ownerDocument->saveXML());
185
    }
186
187
    /**
188
     * @return SAML2_Assertion
189
     */
190
    public function reconstituteAssertion()
191
    {
192
        $assertionAsXML    = $this->stateHandler->getAssertion();
193
        $assertionDocument = new DOMDocument();
194
        $assertionDocument->loadXML($assertionAsXML);
195
196
        return new SAML2_Assertion($assertionDocument->documentElement);
197
    }
198
199
    /**
200
     * @return null|string
201
     */
202
    public function getIdentityNameId()
203
    {
204
        return $this->stateHandler->getIdentityNameId();
205
    }
206
207
    public function getSchacHomeOrganization()
208
    {
209
        return $this->stateHandler->getSchacHomeOrganization();
210
    }
211
212
    /**
213
     * @return null|IdentityProvider
214
     */
215
    public function getAuthenticatingIdp()
216
    {
217
        $entityId = $this->stateHandler->getAuthenticatingIdp();
218
219
        if (!$entityId) {
220
            return null;
221
        }
222
223
        if (isset($this->authenticatingIdp)) {
224
            return $this->authenticatingIdp;
225
        }
226
227
        $this->authenticatingIdp = $this->samlEntityService->hasIdentityProvider($entityId)
228
            ? $this->samlEntityService->getIdentityProvider($entityId)
229
            : null;
230
231
        return $this->authenticatingIdp;
232
    }
233
234
    /**
235
     * @param SecondFactor $secondFactor
236
     */
237
    public function saveSelectedSecondFactor(SecondFactor $secondFactor)
238
    {
239
        $this->stateHandler->setSelectedSecondFactorId($secondFactor->secondFactorId);
240
        $this->stateHandler->setSecondFactorVerified(false);
241
        $this->stateHandler->setPreferredLocale($secondFactor->displayLocale);
242
    }
243
244
    /**
245
     * @return null|string
246
     */
247
    public function getSelectedSecondFactor()
248
    {
249
        return $this->stateHandler->getSelectedSecondFactorId();
250
    }
251
252
    public function markSecondFactorVerified()
253
    {
254
        $this->stateHandler->setSecondFactorVerified(true);
255
    }
256
257
    /**
258
     * @return bool
259
     */
260
    public function isSecondFactorVerified()
261
    {
262
        return $this->stateHandler->getSelectedSecondFactorId() && $this->stateHandler->isSecondFactorVerified();
263
    }
264
265
    public function getResponseAction()
266
    {
267
        return $this->stateHandler->getResponseAction();
268
    }
269
270
    /**
271
     * Resets some state after the response is sent
272
     * (e.g. resets which second factor was selected and whether it was verified).
273
     */
274
    public function responseSent()
275
    {
276
        $this->stateHandler->setSelectedSecondFactorId(null);
277
        $this->stateHandler->setSecondFactorVerified(false);
278
    }
279
}
280