Passed
Pull Request — main (#336)
by
unknown
14:23 queued 06:39
created

getFlowPreferencesFromSamlAttributes()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 13
c 0
b 0
f 0
nc 6
nop 0
dl 0
loc 21
rs 9.5222
1
<?php
2
3
declare(strict_types = 1);
4
5
/**
6
 * Copyright 2022 SURFnet bv
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
Coding Style introduced by
Missing @package tag in file comment
Loading history...
Coding Style introduced by
Missing @author tag in file comment
Loading history...
Coding Style introduced by
Missing @license tag in file comment
Loading history...
Coding Style introduced by
Missing @link tag in file comment
Loading history...
20
21
namespace Surfnet\StepupSelfService\SelfServiceBundle\Service;
22
23
use Psr\Log\LoggerInterface;
24
use Surfnet\StepupSelfService\SelfServiceBundle\Exception\LogicException;
25
use Surfnet\StepupSelfService\SelfServiceBundle\Security\Authentication\AuthenticatedSessionStateHandler;
26
use Surfnet\StepupSelfService\SelfServiceBundle\Value\ActivationFlowPreference;
27
use Surfnet\StepupSelfService\SelfServiceBundle\Value\ActivationFlowPreferenceInterface;
28
use Surfnet\StepupSelfService\SelfServiceBundle\Value\ActivationFlowPreferenceNotExpressed;
29
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
30
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
31
32
class ActivationFlowService
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class ActivationFlowService
Loading history...
33
{
34
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $logger should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $fieldName should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $sessionState should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $tokenStorage should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $attributeName should have a doc-comment as per coding-style.
Loading history...
35
     * Handle preferred activation flow logic
36
     *
37
     * 1. On the / path, the preferred activation flow can be set using the configured
38
     *    query string field. This field can have an option indicating the preferred flow.
39
     *    This is stored in session.
40
     * 2. If this preference was set, the list of available options is limited to just that
41
     *    option.
42
     * 3. The option can be reset by the Identity, removing it from session.
43
     *
44
     * Note that:
45
     * - fieldName and options are configured in the SelfServiceExtension
46
     *
47
     * @param string[] $options
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 14 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Doc comment for parameter $options does not match actual variable name $sessionState
Loading history...
48
     * @param array<string, string> $attributes
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $attributes does not match actual variable name $tokenStorage
Loading history...
49
     */
50
    public function __construct(
51
        private readonly AuthenticatedSessionStateHandler $sessionState,
52
        private readonly TokenStorageInterface $tokenStorage,
53
        private readonly LoggerInterface $logger,
54
        private readonly string $fieldName,
55
        private readonly array $options,
56
        private readonly string $attributeName,
57
        private readonly array $attributes
58
    ) {
59
    }
60
61
    public function processPreferenceFromUri(string $uri): void
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function processPreferenceFromUri()
Loading history...
62
    {
63
        $requestedActivationPreference = $this->getFlowPreferenceFromUri($uri);
64
        if ($requestedActivationPreference instanceof ActivationFlowPreferenceNotExpressed) {
65
            return;
66
        }
67
68
        $this->logger->info('Storing the preference in session');
69
        $this->sessionState->setRequestedActivationFlowPreference($requestedActivationPreference);
70
    }
71
72
    public function getPreference(): ActivationFlowPreferenceInterface
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getPreference()
Loading history...
73
    {
74
        $requestedActivationPreference = $this->sessionState->getRequestedActivationFlowPreference();
75
        $availableActivationPreferences = $this->getFlowPreferencesFromSamlAttributes();
76
77
        if (count($availableActivationPreferences) == 0) {
78
            $this->logger->info('No entitlement attributes found to determine the allowed flow, allowing all flows');
79
            $availableActivationPreferences = [
80
                'ra', 'self'
81
            ];
82
        }
83
84
        if (in_array($requestedActivationPreference, $availableActivationPreferences)) {
85
            $this->logger->info('Found allowed activation flow');
86
            return $requestedActivationPreference;
87
        }
88
89
        $this->logger->info('Not found allowed activation flow');
90
91
        return new ActivationFlowPreferenceNotExpressed();
92
    }
93
94
    private function getFlowPreferenceFromUri(string $uri): ActivationFlowPreferenceInterface
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getFlowPreferenceFromUri()
Loading history...
Coding Style introduced by
Private method name "ActivationFlowService::getFlowPreferenceFromUri" must be prefixed with an underscore
Loading history...
95
    {
96
        $this->logger->info(sprintf('Analysing uri "%s" for activation flow query parameter', $uri));
97
98
        $parts = parse_url($uri);
99
        /** @var array<string, string> $parameters */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
100
        $parameters = [];
101
102
        if (array_key_exists('query', $parts)) {
103
            $this->logger->debug('Found a query string in the uri');
104
            parse_str($parts['query'], $parameters);
105
        }
106
107
        // Is the configured field name in the querystring?
108
        if (!array_key_exists($this->fieldName, $parameters)) {
109
            $this->logger->notice(
110
                sprintf(
111
                    'The configured query string field name "%s" was not found in the uri "%s"',
112
                    $this->fieldName,
113
                    $uri
114
                )
115
            );
116
            return new ActivationFlowPreferenceNotExpressed();
117
        }
118
119
        $option = $parameters[$this->fieldName];
120
        switch ($option) {
121
            case 'ra':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
122
                return ActivationFlowPreference::createRa();
123
            case 'self':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
124
                return ActivationFlowPreference::createSelf();
125
        }
126
127
128
        $this->logger->notice(
129
            sprintf(
130
                'Field "%s" contained an invalid option "%s", must be one of: %s',
131
                $this->fieldName,
132
                $option,
133
                implode(', ', $this->options)
134
            )
135
        );
136
        return new ActivationFlowPreferenceNotExpressed();
137
    }
138
139
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
140
     * @return ActivationFlowPreferenceInterface[]
141
     */
142
    private function getFlowPreferencesFromSamlAttributes(): array
0 ignored issues
show
Coding Style introduced by
Private method name "ActivationFlowService::getFlowPreferencesFromSamlAttributes" must be prefixed with an underscore
Loading history...
143
    {
144
        $this->logger->info('Analysing saml entitlement attributes for allowed activation flows');
145
146
        $token = $this->tokenStorage->getToken();
147
        if (!$token instanceof TokenInterface) {
148
            throw new LogicException("A authentication token should be set at this point");
149
        }
150
151
        $activationFlows = [];
152
        $attributes = $token->getAttributes();
153
        if (array_key_exists($this->attributeName, $attributes)) {
154
            $this->logger->debug('Found entitlement saml attributes');
155
            if (in_array($this->attributes['ra'], $attributes[$this->attributeName])) {
156
                $activationFlows[] = ActivationFlowPreference::createRa();
157
            }
158
            if (in_array($this->attributes['self'], $attributes[$this->attributeName])) {
159
                $activationFlows[] = ActivationFlowPreference::createSelf();
160
            }
161
        }
162
        return $activationFlows;
163
    }
164
}
165