Completed
Push — feature/use-authn-request-acs-... ( 6c793d...703fc0 )
by
unknown
05:59
created

ServiceProvider   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 124
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 13
c 0
b 0
f 0
lcom 1
cbo 4
dl 0
loc 124
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A mayUseGateway() 0 4 1
A mayUseSecondFactorOnly() 0 4 1
B isAllowedToUseSecondFactorOnlyFor() 0 22 6
A determineAcsLocation() 0 18 2
A determineAcsLocationforAdfs() 0 17 3
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\Entity;
20
21
use Psr\Log\LoggerInterface;
22
use Surfnet\SamlBundle\Entity\ServiceProvider as BaseServiceProvider;
23
use Surfnet\StepupGateway\GatewayBundle\Exception\InvalidArgumentException;
24
use Surfnet\StepupGateway\SecondFactorOnlyBundle\Adfs\Exception\AcsLocationNotAllowedException;
25
26
class ServiceProvider extends BaseServiceProvider
27
{
28
    /**
29
     * @return bool
30
     */
31
    public function mayUseGateway()
32
    {
33
        return !$this->mayUseSecondFactorOnly();
34
    }
35
36
    /**
37
     * @return bool
38
     */
39
    public function mayUseSecondFactorOnly()
40
    {
41
        return (bool) $this->get('secondFactorOnly', false);
42
    }
43
44
    /**
45
     * @param string $nameId
46
     * @return bool
47
     */
48
    public function isAllowedToUseSecondFactorOnlyFor($nameId)
49
    {
50
        if (!is_string($nameId)) {
51
            throw InvalidArgumentException::invalidType('string', 'nameId', $nameId);
52
        }
53
54
        if (empty($nameId)) {
55
            return false;
56
        }
57
58
        if (!$this->mayUseSecondFactorOnly()) {
59
            return false;
60
        }
61
62
        $nameIdPatterns = $this->get('secondFactorOnlyNameIdPatterns');
63
        foreach ($nameIdPatterns as $nameIdPattern) {
64
            if ((bool) preg_match('#^' . strtr(preg_quote($nameIdPattern, '#'), ['\*' => '.*']) . '$#', $nameId)) {
65
                return true;
66
            }
67
        }
68
        return false;
69
    }
70
71
    /**
72
     * Determine the ACS location to send the response to.
73
     *
74
     * The get getAssertionConsumerUrl() method returns a trusted ACS location
75
     * for this service provider. This value is set when the service provider
76
     * is "internal", for example when it is configured in yaml
77
     * configuration.
78
     *
79
     * Methods like Surfnet\SamlBundle\Http\PostBinding::processResponse use
80
     * this trusted value. When the ServiceProvider is external, this value is
81
     * empty and the ACS location found in the AuthnRequest should be used, if
82
     * it matches one of the configured allowed ACS locations for the service
83
     * provider. This methods checks if a given URL matches the allowed URLs.
84
     *
85
     * @param LoggerInterface $logger
86
     * @param $acsLocationInAuthnRequest
87
     * @return string
88
     */
89
    public function determineAcsLocation(LoggerInterface $logger, $acsLocationInAuthnRequest)
90
    {
91
        // List of allowed ACS locations configured in middleware.
92
        $allowedAcsLocations = $this->get('allowedAcsLocations');
93
94
        if (in_array($acsLocationInAuthnRequest, $allowedAcsLocations)) {
95
            return $acsLocationInAuthnRequest;
96
        }
97
98
        $logger->warning(
99
            sprintf(
100
                'AuthnRequest requests ACS location "%s" but it is not configured in the list of allowed ACS locations',
101
                $acsLocationInAuthnRequest
102
            )
103
        );
104
105
        return reset($allowedAcsLocations);
106
    }
107
108
    /**
109
     * Determine the ACS location for ADFS to send the response to.
110
     *
111
     * This method is similar to determineAcsLocation(), but does not check
112
     * for the requested ACS location to be identical to one of the configured
113
     * ACS locations, but only if matches the first part of an allowed URL.
114
     *
115
     * For example, ADFS might send an ACS location like:
116
     *
117
     *     https://example.com/consume-assertion?key=value
118
     *
119
     * Above URL is allowed if one of the configured URLs is:
120
     *
121
     *     https://example.com/consume-assertion
122
     *
123
     * Or:
124
     *
125
     *     https://example.com/consume
126
     *
127
     *
128
     * @param LoggerInterface $logger
129
     * @param $acsLocationInAuthnRequest
130
     * @return string
131
     */
132
    public function determineAcsLocationforAdfs(LoggerInterface $logger, $acsLocationInAuthnRequest)
0 ignored issues
show
Unused Code introduced by
The parameter $logger is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
133
    {
134
        // List of allowed ACS locations configured in middleware.
135
        $allowedAcsLocations = $this->get('allowedAcsLocations');
136
137
        foreach ($allowedAcsLocations as $allowedAcsLocation) {
138
            if (strpos($acsLocationInAuthnRequest, $allowedAcsLocation) === 0) {
139
                return $acsLocationInAuthnRequest;
140
            }
141
        }
142
143
        // The exception listener will log relevant information to the log.
144
145
        throw new AcsLocationNotAllowedException(
146
            $acsLocationInAuthnRequest
147
        );
148
    }
149
}
150