Completed
Push — master ( 876946...08c288 )
by Bart
02:55
created

ShibbolethServiceProvider::getStatusPath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Kuleuven\AuthenticationBundle\Service;
4
5
use Symfony\Component\HttpFoundation\Request;
6
use Symfony\Component\HttpFoundation\RequestStack;
7
8
class ShibbolethServiceProvider implements AttributesByUsernameProviderInterface
9
{
10
    /**
11
     * @var RequestStack
12
     */
13
    protected $requestStack;
14
15
    /**
16
     * @var AttributeDefinitionsProviderInterface
17
     */
18
    protected $attributeDefinitionsProvider;
19
20
    /**
21
     * @var bool
22
     */
23
    protected $securedHandler;
24
25
    /**
26
     * @var string
27
     */
28
    protected $handlerPath;
29
30
    /**
31
     * @var string
32
     */
33
    protected $statusPath;
34
35
    /**
36
     * @var string
37
     */
38
    protected $sessionLoginPath;
39
40
    /**
41
     * @var string
42
     */
43
    protected $sessionLogoutPath;
44
45
    /**
46
     * @var string
47
     */
48
    protected $sessionOverviewPath;
49
50
    /**
51
     * @var string
52
     */
53
    protected $usernameAttribute;
54
55
    /**
56
     * @var string
57
     */
58
    protected $authenticatedAttribute;
59
60
    /**
61
     * @var string
62
     */
63
    protected $logoutUrlAttribute;
64
65
    /**
66
     * @var array
67
     */
68
    protected $authenticationRequirements;
69
70
    /**
71
     * @var string
72
     */
73
    protected $defaultCharset;
74
75
    /**
76
     * @var Request
77
     */
78
    protected $request;
79
80
    /**
81
     * @var bool
82
     */
83
    protected $authenticated;
84
85
    /**
86
     * @param RequestStack                          $requestStack
87
     * @param AttributeDefinitionsProviderInterface $attributeDefinitionsProvider
88
     * @param bool                                  $securedHandler
89
     * @param string                                $handlerPath
90
     * @param string                                $statusPath
91
     * @param string                                $sessionLoginPath
92
     * @param string                                $sessionLogoutPath
93
     * @param string                                $sessionOverviewPath
94
     * @param string                                $usernameAttribute
95
     * @param string                                $logoutUrlAttribute
96
     * @param array                                 $authenticationRequirements
97
     * @param string                                $defaultCharset
98
     */
99
    public function __construct(
100
        RequestStack $requestStack,
101
        AttributeDefinitionsProviderInterface $attributeDefinitionsProvider,
102
        $securedHandler,
103
        $handlerPath,
104
        $statusPath,
105
        $sessionLoginPath,
106
        $sessionLogoutPath,
107
        $sessionOverviewPath,
108
        $usernameAttribute,
109
        $authenticatedAttribute,
110
        $logoutUrlAttribute,
111
        $authenticationRequirements,
112
        $defaultCharset
113
    )
114
    {
115
        $this->requestStack = $requestStack;
116
        $this->attributeDefinitionsProvider = $attributeDefinitionsProvider;
117
        $this->securedHandler = $securedHandler;
118
        $this->handlerPath = $handlerPath;
119
        $this->statusPath = $statusPath;
120
        $this->sessionLoginPath = $sessionLoginPath;
121
        $this->sessionLogoutPath = $sessionLogoutPath;
122
        $this->sessionOverviewPath = $sessionOverviewPath;
123
        $this->usernameAttribute = $usernameAttribute;
124
        $this->authenticatedAttribute = $authenticatedAttribute;
125
        $this->logoutUrlAttribute = $logoutUrlAttribute;
126
        $this->authenticationRequirements = $authenticationRequirements;
127
        $this->defaultCharset = $defaultCharset;
128
129
        return $this;
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
130
    }
131
132
    /**
133
     * @return bool
134
     */
135
    public function isSecuredHandler()
136
    {
137
        return $this->securedHandler;
138
    }
139
140
    /**
141
     * @return string
142
     */
143
    public function getHandlerPath()
144
    {
145
        return $this->handlerPath;
146
    }
147
148
    /**
149
     * @return string
150
     */
151
    public function getSessionLoginPath()
152
    {
153
        return $this->sessionLoginPath;
154
    }
155
156
    /**
157
     * @return string
158
     */
159
    public function getSessionLogoutPath()
160
    {
161
        return $this->sessionLogoutPath;
162
    }
163
164
    /**
165
     * @return string
166
     */
167
    public function getSessionOverviewPath()
168
    {
169
        return $this->sessionOverviewPath;
170
    }
171
172
    /**
173
     * @return string
174
     */
175
    public function getStatusPath()
176
    {
177
        return $this->statusPath;
178
    }
179
180
    /**
181
     * @return Request
182
     */
183
    protected function getRequest()
184
    {
185
        if (empty($this->request)) {
186
            $this->request = $this->requestStack->getCurrentRequest();
187
        }
188
189
        return $this->request;
190
    }
191
192
    /**
193
     * @param null $fallback
194
     * @return array
195
     */
196
    public function getAttributes($fallback = null)
197
    {
198
        $attributeDefinitions = $this->attributeDefinitionsProvider->getAttributeDefinitions();
199
        $attributes = [];
200
        foreach ($attributeDefinitions as $idOrAlias => $attributeDefinition) {
201
            $attributes[$idOrAlias] = $this->getAttribute($idOrAlias, $fallback);
202
        }
203
        return $attributes;
204
    }
205
206
    /**
207
     * @param string $name
208
     * @param null   $fallback
209
     * @return null|string
210
     */
211
    public function getAttribute($name, $fallback = null)
212
    {
213
        $request = $this->requestStack->getCurrentRequest();
214
        return $request->server->get($name, $fallback);
215
    }
216
217
    /**
218
     * @param string $name
219
     * @return bool
220
     */
221
    public function hasAttribute($name)
222
    {
223
        $empty = microtime(true);
224
        return $empty !== $this->getAttribute($name, $empty);
225
    }
226
227
    /**
228
     * @param array $keyValues
229
     * @return bool
230
     */
231
    public function hasAttributeValues(array $keyValues)
232
    {
233
        $result = true;
234
        $empty = microtime(true);
235
        set_error_handler(function ($errno, $errstr) {
236
            throw new \Exception($errstr, $errno);
237
        });
238
        foreach ($keyValues as $checkName => $checkValue) {
239
            $value = $this->getAttribute($checkName, $empty);
240
            if ($checkValue !== $value) {
241
                try {
242
                    $result = preg_match($checkValue, $value);
243
                } catch (\Exception $e) {
244
                    $result = false;
245
                }
246
            }
247
            if (!$result) {
248
                break;
249
            }
250
        }
251
        restore_error_handler();
252
        return $result;
253
    }
254
255
    /**
256
     * @return bool
257
     */
258
    public function isAuthenticated()
259
    {
260
        if (null === $this->authenticated) {
261
            $this->authenticated = $this->hasAttributeValues($this->getAuthenticationRequirements());
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->hasAttributeValue...ticationRequirements()) can also be of type integer. However, the property $authenticated is declared as type boolean. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
262
        }
263
264
        return $this->authenticated;
265
    }
266
267
    /**
268
     * @return string
269
     */
270
    public function getUsername()
271
    {
272
        return $this->getAttribute($this->usernameAttribute);
273
    }
274
275
    /**
276
     * @param $username
277
     * @return array
278
     */
279
    public function getAttributesByUsername($username)
280
    {
281
        if ($username !== $this->getUsername()) {
282
            return [];
283
        }
284
285
        return $this->getAttributes(null);
286
    }
287
288
    /**
289
     * Returns shibboleth session URL
290
     *
291
     * @return string
292
     */
293
    public function getHandlerUrl()
294
    {
295
        $request = $this->getRequest();
296
        return (($this->isSecuredHandler()) ? 'https://' : 'http://') . $request->getHost() . $this->getHandlerPath();
297
    }
298
299
    /**
300
     * Returns URL to initiate login session. After successful login, the user will be redirected
301
     * to the optional target page. The target can be an absolute or relative URL.
302
     *
303
     * @param string|null $target URL to redirect to after successful login. Defaults to the current request URL.
304
     * @return string The absolute URL to initiate a session
305
     */
306
    public function getLoginUrl($target = null)
307
    {
308
        $request = $this->getRequest();
309
        if (empty($target)) {
310
            $target = $request->getUri();
311
        }
312
        return $this->getHandlerUrl() . $this->getSessionLoginPath() . '?target=' . urlencode($target);
313
    }
314
315
    /**
316
     * Returns URL to invalidate the shibboleth session.
317
     *
318
     * @param null $target URL to redirect to after successful logout. Defaults to the current request URL.
319
     * @return string
320
     */
321
    public function getLogoutUrl($target = null)
322
    {
323
        $request = $this->getRequest();
324
        if (empty($target)) {
325
            $target = $request->getUri();
326
        }
327
        $logoutUrl = $this->getAttribute($this->logoutUrlAttribute);
328
        if (!empty($logoutUrl)) {
329
            return $this->getHandlerUrl() . $this->getSessionLogoutPath()
330
            . '?return=' . urlencode($logoutUrl . (empty($target) ? '' : '?return=' . $target));
331
        }
332
        return $this->getHandlerUrl() . $this->getSessionLogoutPath() . '?return=' . urlencode($target);
333
    }
334
335
    /**
336
     * Returns URL to show session.
337
     *
338
     * @return string The absolute URL to show a session
339
     */
340
    public function getOverviewUrl()
341
    {
342
        return $this->getHandlerUrl() . $this->getSessionOverviewPath();
343
    }
344
345
    /**
346
     * Returns URL to show status.
347
     *
348
     * @return string The absolute URL to show the status
349
     */
350
    public function getStatusUrl()
351
    {
352
        return $this->getHandlerUrl() . $this->getStatusPath();
353
    }
354
355
    /**
356
     * @deprecated
357
     * @return string
358
     */
359
    public function getSessionInitiatorPath()
360
    {
361
        return $this->sessionLoginPath;
362
    }
363
364
    /**
365
     * @return string
366
     */
367
    public function getUsernameAttribute()
368
    {
369
        return $this->usernameAttribute;
370
    }
371
372
    /**
373
     * @return string
374
     */
375
    public function getAuthenticatedAttribute()
376
    {
377
        return $this->authenticatedAttribute;
378
    }
379
380
    /**
381
     * @return string
382
     */
383
    public function getLogoutUrlAttribute()
384
    {
385
        return $this->logoutUrlAttribute;
386
    }
387
388
    /**
389
     * @return string
390
     */
391
    public function getAuthenticationRequirements()
392
    {
393
        return $this->authenticationRequirements;
394
    }
395
396
    /**
397
     * @return string
398
     */
399
    public function getDefaultCharset()
400
    {
401
        return $this->defaultCharset;
402
    }
403
404
    /**
405
     * @param null|string $url
406
     * @return bool
407
     */
408
    public function isReachable($url = null)
409
    {
410
        if (null === $url) {
411
            $url = $this->getStatusUrl();
412
        }
413
        $handle = curl_init($url);
414
        if (false === $handle) {
415
            return false;
416
        }
417
        curl_setopt($handle, CURLOPT_FOLLOWLOCATION, true);
418
        curl_setopt($handle, CURLOPT_HEADER, false);
419
        curl_setopt($handle, CURLOPT_FAILONERROR, true);
420
        curl_setopt($handle, CURLOPT_NOBODY, true);
421
        curl_setopt($handle, CURLOPT_RETURNTRANSFER, false);
422
        $succeeded = curl_exec($handle);
423
        curl_close($handle);
424
        if (false === $succeeded) {
425
            return false;
426
        }
427
        return true;
428
    }
429
}
430