Passed
Push — master ( 0c43bc...4ec253 )
by Tim
02:55
created

ServiceProvider::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
c 1
b 0
f 0
nc 1
nop 11
dl 0
loc 15
rs 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\Entity;
6
7
use Exception;
8
use Psr\Http\Message\ServerRequestInterface;
9
use SimpleSAML\Assert\Assert;
10
use SimpleSAML\SAML2\{
11
    Binding,
12
    Metadata,
13
    MetadataProviderInterface,
14
    StateProviderInterface,
15
    StorageProviderInterface,
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\StorageProviderInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
    Utils,
17
};
18
use SimpleSAML\SAML2\Binding\HTTPArtifact;
19
use SimpleSAML\SAML2\Exception\{MetadataNotFoundException, RemoteException, RuntimeException};
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\Exception\RemoteException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
20
use SimpleSAML\SAML2\Exception\Protocol\{RequestDeniedException, ResourceNotRecognizedException};
21
use SimpleSAML\SAML2\Process\Validator\ResponseValidator;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\Process...dator\ResponseValidator was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
22
use SimpleSAML\SAML2\XML\saml\{
23
    Assertion,
24
    AttributeStatement,
25
    EncryptedAssertion,
26
    EncryptedAttribute,
27
    EncryptedID,
28
    Subject,
29
};
30
use SimpleSAML\SAML2\XML\samlp\Response;
31
use SimpleSAML\XMLSecurity\Alg\Encryption\EncryptionAlgorithmFactory;
32
use SimpleSAML\XMLSecurity\Exception\SignatureVerificationFailedException;
33
use SimpleSAML\XMLSecurity\XML\{
34
    EncryptableElementInterface,
35
    EncryptedElementInterface,
36
    SignableElementInterface,
37
    SignedElementInterface,
38
};
39
40
use function sprintf;
41
42
/**
43
 * Class representing a SAML 2 Service Provider.
44
 *
45
 * @package simplesamlphp/saml2
46
 */
47
final class ServiceProvider
48
{
49
    protected ?StateProviderInterface $stateProvider = null;
50
    protected ?StorageProviderInterface $storageProvider = null;
51
    protected ?Metadata\IdentityProvider $idpMetadata = null;
52
53
54
    /**
55
     * @param bool $encryptedAssertions  Whether assertions must be encrypted
56
     * @param bool $disableScoping  Whether to send the samlp:Scoping element in requests
57
     * @param bool $enableUnsolicited  Whether to process unsolicited responses
58
     * @param bool $encryptNameId  Whether to encrypt the NameID sent
59
     * @param bool $signAuthnRequest  Whether to sign the AuthnRequest sent
60
     * @param bool $signLogout  Whether to sign the LogoutRequest/LogoutResponse sent
61
     * @param bool $validateLogout  Whether to validate the signature of LogoutRequest/LogoutResponse received
62
     */
63
    public function __construct(
64
        protected MetadataProviderInterface $metadataProvider,
65
        protected Metadata\ServiceProvider $spMetadata,
66
        protected readonly bool $encryptedAssertions = false,
67
        protected readonly bool $disableScoping = false,
68
        protected readonly bool $enableUnsolicited = false,
69
        protected readonly bool $encryptNameId = false,
70
        protected readonly bool $signAuthnRequest = false,
71
        protected readonly bool $signLogout = false,
72
        protected readonly bool $validateLogout = true,
73
        // Use with caution - will leave any form of signature verification or token decryption up to the implementer
74
        protected readonly bool $bypassResponseVerification = false,
75
        // Use with caution - will leave any form of constraint validation up to the implementer
76
        protected readonly bool $bypassConstraintValidation = false,
77
    ) {
78
    }
79
80
81
    /**
82
     */
83
    public function setStateProvider(StateProviderInterface $stateProvider): void
84
    {
85
        $this->stateProvider = $stateProvider;
86
    }
87
88
89
    /**
90
     */
91
    public function setStorageProvider(StorageProviderInterface $storageProvider): void
92
    {
93
        $this->storageProvider = $storageProvider;
94
    }
95
96
97
    /**
98
     * Receive a verified, and optionally validated Response.
99
     *
100
     * Upon receiving the response from the binding, the signature will be validated first.
101
     * Once the signature checks out, the assertions are decrypted, their signatures verified
102
     *  and then any encrypted NameID's and/or attributes are decrypted.
103
     *
104
     * @param \Psr\Http\Message\ServerRequestInterface $request
105
     * @return \SimpleSAML\SAML2\XML\samlp\Response The validated response.
106
     *
107
     * @throws \SimpleSAML\SAML2\Exception\Protocol\UnsupportedBindingException
108
     */
109
    public function receiveResponse(ServerRequestInterface $request): Response
110
    {
111
        $binding = Binding::getCurrentBinding($request);
112
113
        if ($binding instanceof HTTPArtifact) {
114
            if ($this->storageProvider === null) {
115
                throw new RuntimeException(
116
                    "A StorageProvider is required to use the HTTP-Artifact binding.",
117
                );
118
            }
119
120
            $artifact = $binding->receiveArtifact($request);
0 ignored issues
show
Bug introduced by
The method receiveArtifact() does not exist on SimpleSAML\SAML2\Binding\HTTPArtifact. Did you maybe mean receive()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

120
            /** @scrutinizer ignore-call */ 
121
            $artifact = $binding->receiveArtifact($request);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
121
            $this->idpMetadata = $this->metadataProvider->getIdPMetadataForSha1($artifact->getSourceId());
122
123
            if ($this->idpMetadata === null) {
124
                throw new MetadataNotFoundException(sprintf(
125
                    'No metadata found for remote entity with SHA1 ID: %s',
126
                    $artifact->getSourceId(),
127
                ));
128
            }
129
130
            $binding->setIdpMetadata($this->idpMetadata);
0 ignored issues
show
Bug introduced by
The method setIdpMetadata() does not exist on SimpleSAML\SAML2\Binding\HTTPArtifact. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

130
            $binding->/** @scrutinizer ignore-call */ 
131
                      setIdpMetadata($this->idpMetadata);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
131
            $binding->setSPMetadata($this->spMetadata);
132
        }
133
134
        $rawResponse = $binding->receive($request);
135
        Assert::isInstanceOf($rawResponse, Response::class, ResourceNotRecognizedException::class); // Wrong type of msg
136
137
        // Will return a raw Response prior to any form of verification
138
        if ($this->bypassResponseVerification === true) {
139
            return $rawResponse;
140
        }
141
142
        // Fetch the metadata for the remote entity
143
        if (!($binding instanceof HTTPArtifact)) {
144
            $this->idpMetadata = $this->metadataProvider->getIdPMetadata($rawResponse->getIssuer()->getContent());
145
146
            if ($this->idpMetadata === null) {
147
                throw new MetadataNotFoundException(sprintf(
148
                    'No metadata found for remote entity with entityID: %s',
149
                    $rawResponse->getIssuer()->getContent(),
150
                ));
151
            }
152
        }
153
154
        // Verify the signature (if any)
155
        $verifiedResponse = $rawResponse->isSigned() ? $this->verifyElementSignature($rawResponse) : $rawResponse;
156
157
        $state = null;
158
        $stateId = $verifiedResponse->getInResponseTo();
0 ignored issues
show
Bug introduced by
The method getInResponseTo() does not exist on SimpleSAML\SAML2\XML\samlp\ArtifactResolve. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

158
        /** @scrutinizer ignore-call */ 
159
        $stateId = $verifiedResponse->getInResponseTo();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getInResponseTo() does not exist on SimpleSAML\XMLSecurity\X...ignableElementInterface. It seems like you code against a sub-type of SimpleSAML\XMLSecurity\X...ignableElementInterface such as SimpleSAML\SAML2\XML\samlp\AbstractStatusResponse. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

158
        /** @scrutinizer ignore-call */ 
159
        $stateId = $verifiedResponse->getInResponseTo();
Loading history...
Bug introduced by
The method getInResponseTo() does not exist on SimpleSAML\SAML2\XML\samlp\AbstractMessage. It seems like you code against a sub-type of SimpleSAML\SAML2\XML\samlp\AbstractMessage such as SimpleSAML\SAML2\XML\samlp\AbstractStatusResponse. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

158
        /** @scrutinizer ignore-call */ 
159
        $stateId = $verifiedResponse->getInResponseTo();
Loading history...
Bug introduced by
The method getInResponseTo() does not exist on SimpleSAML\SAML2\XML\samlp\LogoutRequest. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

158
        /** @scrutinizer ignore-call */ 
159
        $stateId = $verifiedResponse->getInResponseTo();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getInResponseTo() does not exist on SimpleSAML\SAML2\XML\samlp\AuthnRequest. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

158
        /** @scrutinizer ignore-call */ 
159
        $stateId = $verifiedResponse->getInResponseTo();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getInResponseTo() does not exist on SimpleSAML\SAML2\XML\samlp\AttributeQuery. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

158
        /** @scrutinizer ignore-call */ 
159
        $stateId = $verifiedResponse->getInResponseTo();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
159
160
        if (!empty($stateId)) {
161
            if ($this->stateProvider === null) {
162
                throw new RuntimeException(
163
                    "A StateProvider is required to correlate responses to their initial request.",
164
                );
165
            }
166
167
            // this should be a response to a request we sent earlier
168
            try {
169
                $state = $this->stateProvider::loadState($stateId, 'saml:sp:sso');
170
            } catch (RuntimeException $e) {
171
                // something went wrong,
172
                Utils::getContainer()->getLogger()->warning(sprintf(
173
                    'Could not load state specified by InResponseTo: %s; processing response as unsolicited.',
174
                    $e->getMessage(),
175
                ));
176
            }
177
        }
178
179
        $issuer = $verifiedResponse->getIssuer()->getContent();
0 ignored issues
show
Bug introduced by
The method getIssuer() does not exist on SimpleSAML\XMLSecurity\X...ignableElementInterface. It seems like you code against a sub-type of SimpleSAML\XMLSecurity\X...ignableElementInterface such as SimpleSAML\SAML2\XML\samlp\AbstractMessage or SimpleSAML\SAML2\XML\saml\Assertion. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

179
        $issuer = $verifiedResponse->/** @scrutinizer ignore-call */ getIssuer()->getContent();
Loading history...
180
        if ($state === null) {
181
            if ($this->enableUnsolicited === false) {
182
                throw new RequestDeniedException('Unsolicited responses are denied by configuration.');
183
            }
184
        } else {
185
            // check that the issuer is the one we are expecting
186
            Assert::keyExists($state, 'ExpectedIssuer');
187
188
            if ($state['ExpectedIssuer'] !== $issuer) {
189
                throw new ResourceNotRecognizedException("Issuer doesn't match the one the AuthnRequest was sent to.");
190
            }
191
        }
192
193
        $this->idpMetadata = $this->metadataProvider->getIdPMetadata($issuer);
194
        if ($this->idpMetadata === null) {
195
            throw new MetadataNotFoundException(sprintf(
196
                'No metadata found for remote identity provider with entityID: %s',
197
                $issuer,
198
            ));
199
        }
200
201
        $responseValidator = ResponseValidator::createResponseValidator(
202
            $this->idpMetadata,
203
            $this->spMetadata,
204
            $binding,
205
        );
206
        $responseValidator->validate($verifiedResponse);
207
208
        // Decrypt and verify assertions, then rebuild the response.
209
        $verifiedAssertions = $this->decryptAndVerifyAssertions($verifiedResponse->getAssertions());
0 ignored issues
show
Bug introduced by
The method getAssertions() does not exist on SimpleSAML\SAML2\XML\samlp\AttributeQuery. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

209
        $verifiedAssertions = $this->decryptAndVerifyAssertions($verifiedResponse->/** @scrutinizer ignore-call */ getAssertions());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getAssertions() does not exist on SimpleSAML\SAML2\XML\samlp\AbstractMessage. It seems like you code against a sub-type of SimpleSAML\SAML2\XML\samlp\AbstractMessage such as SimpleSAML\SAML2\XML\samlp\Response. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

209
        $verifiedAssertions = $this->decryptAndVerifyAssertions($verifiedResponse->/** @scrutinizer ignore-call */ getAssertions());
Loading history...
Bug introduced by
The method getAssertions() does not exist on SimpleSAML\SAML2\XML\samlp\AuthnRequest. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

209
        $verifiedAssertions = $this->decryptAndVerifyAssertions($verifiedResponse->/** @scrutinizer ignore-call */ getAssertions());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getAssertions() does not exist on SimpleSAML\SAML2\XML\samlp\ArtifactResolve. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

209
        $verifiedAssertions = $this->decryptAndVerifyAssertions($verifiedResponse->/** @scrutinizer ignore-call */ getAssertions());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getAssertions() does not exist on SimpleSAML\SAML2\XML\samlp\LogoutResponse. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

209
        $verifiedAssertions = $this->decryptAndVerifyAssertions($verifiedResponse->/** @scrutinizer ignore-call */ getAssertions());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getAssertions() does not exist on SimpleSAML\SAML2\XML\samlp\LogoutRequest. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

209
        $verifiedAssertions = $this->decryptAndVerifyAssertions($verifiedResponse->/** @scrutinizer ignore-call */ getAssertions());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getAssertions() does not exist on SimpleSAML\SAML2\XML\samlp\ArtifactResponse. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

209
        $verifiedAssertions = $this->decryptAndVerifyAssertions($verifiedResponse->/** @scrutinizer ignore-call */ getAssertions());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getAssertions() does not exist on SimpleSAML\XMLSecurity\X...ignableElementInterface. It seems like you code against a sub-type of SimpleSAML\XMLSecurity\X...ignableElementInterface such as SimpleSAML\SAML2\XML\samlp\Response. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

209
        $verifiedAssertions = $this->decryptAndVerifyAssertions($verifiedResponse->/** @scrutinizer ignore-call */ getAssertions());
Loading history...
210
        $decryptedResponse = new Response(
211
            $verifiedResponse->getStatus(),
0 ignored issues
show
Bug introduced by
The method getStatus() does not exist on SimpleSAML\SAML2\XML\samlp\LogoutRequest. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

211
            $verifiedResponse->/** @scrutinizer ignore-call */ 
212
                               getStatus(),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getStatus() does not exist on SimpleSAML\XMLSecurity\X...ignableElementInterface. It seems like you code against a sub-type of SimpleSAML\XMLSecurity\X...ignableElementInterface such as SimpleSAML\SAML2\XML\samlp\AbstractStatusResponse. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

211
            $verifiedResponse->/** @scrutinizer ignore-call */ 
212
                               getStatus(),
Loading history...
Bug introduced by
The method getStatus() does not exist on SimpleSAML\SAML2\XML\samlp\ArtifactResolve. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

211
            $verifiedResponse->/** @scrutinizer ignore-call */ 
212
                               getStatus(),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getStatus() does not exist on SimpleSAML\SAML2\XML\samlp\AuthnRequest. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

211
            $verifiedResponse->/** @scrutinizer ignore-call */ 
212
                               getStatus(),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getStatus() does not exist on SimpleSAML\SAML2\XML\samlp\AttributeQuery. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

211
            $verifiedResponse->/** @scrutinizer ignore-call */ 
212
                               getStatus(),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getStatus() does not exist on SimpleSAML\SAML2\XML\samlp\AbstractMessage. It seems like you code against a sub-type of SimpleSAML\SAML2\XML\samlp\AbstractMessage such as SimpleSAML\SAML2\XML\samlp\AbstractStatusResponse. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

211
            $verifiedResponse->/** @scrutinizer ignore-call */ 
212
                               getStatus(),
Loading history...
212
            $verifiedResponse->getIssueInstant(),
0 ignored issues
show
Bug introduced by
The method getIssueInstant() does not exist on SimpleSAML\XMLSecurity\X...ignableElementInterface. It seems like you code against a sub-type of SimpleSAML\XMLSecurity\X...ignableElementInterface such as SimpleSAML\SAML2\XML\samlp\AbstractMessage or SimpleSAML\SAML2\XML\saml\Assertion. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

212
            $verifiedResponse->/** @scrutinizer ignore-call */ 
213
                               getIssueInstant(),
Loading history...
213
            $verifiedResponse->getIssuer(),
214
            $verifiedResponse->getID(),
215
            $verifiedResponse->getVersion(),
0 ignored issues
show
Bug introduced by
The method getVersion() does not exist on SimpleSAML\XMLSecurity\X...ignableElementInterface. It seems like you code against a sub-type of SimpleSAML\XMLSecurity\X...ignableElementInterface such as SimpleSAML\SAML2\XML\samlp\AbstractMessage. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

215
            $verifiedResponse->/** @scrutinizer ignore-call */ 
216
                               getVersion(),
Loading history...
216
            $verifiedResponse->getInResponseTo(),
217
            $verifiedResponse->getDestination(),
0 ignored issues
show
Bug introduced by
The method getDestination() does not exist on SimpleSAML\XMLSecurity\X...ignableElementInterface. It seems like you code against a sub-type of SimpleSAML\XMLSecurity\X...ignableElementInterface such as SimpleSAML\SAML2\XML\samlp\AbstractMessage. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

217
            $verifiedResponse->/** @scrutinizer ignore-call */ 
218
                               getDestination(),
Loading history...
218
            $verifiedResponse->getConsent(),
0 ignored issues
show
Bug introduced by
The method getConsent() does not exist on SimpleSAML\XMLSecurity\X...ignableElementInterface. It seems like you code against a sub-type of SimpleSAML\XMLSecurity\X...ignableElementInterface such as SimpleSAML\SAML2\XML\samlp\AbstractMessage. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

218
            $verifiedResponse->/** @scrutinizer ignore-call */ 
219
                               getConsent(),
Loading history...
219
            $verifiedResponse->getExtensions(),
0 ignored issues
show
Bug introduced by
The method getExtensions() does not exist on SimpleSAML\XMLSecurity\X...ignableElementInterface. It seems like you code against a sub-type of SimpleSAML\XMLSecurity\X...ignableElementInterface such as SimpleSAML\SAML2\XML\samlp\AbstractMessage or SimpleSAML\SAML2\XML\md\AbstractMetadataDocument. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

219
            $verifiedResponse->/** @scrutinizer ignore-call */ 
220
                               getExtensions(),
Loading history...
220
            $verifiedAssertions,
221
        );
222
223
224
        // Will return a verified and fully decrypted Response prior to any form of validation
225
        if ($this->bypassConstraintValidation === true) {
226
            return $decryptedResponse;
227
        }
228
229
        // TODO: Validate assertions
230
        return $decryptedResponse;
231
    }
232
233
234
    /**
235
     * Process the assertions and decrypt any encrypted elements inside.
236
     *
237
     * @param \SimpleSAML\SAML2\XML\saml\Assertion[] $unverifiedAssertions
238
     * @return \SimpleSAML\SAML2\XML\saml\Assertion[]
239
     *
240
     * @throws \SimpleSAML\SAML2\Exception\RuntimeException if none of the keys could be used to decrypt the element
241
     */
242
    protected function decryptAndVerifyAssertions(array $unverifiedAssertions): array
243
    {
244
        /**
245
         * See paragraph 6.2 of the SAML 2.0 core specifications for the applicable processing rules
246
         *
247
         * Long story short - Decrypt the assertion first, then validate it's signature
248
         * Once the signature is verified, decrypt any BaseID, NameID or Attribute that's encrypted
249
         */
250
        $verifiedAssertions = [];
251
        foreach ($unverifiedAssertions as $i => $assertion) {
252
            // Decrypt the assertions
253
            $decryptedAssertion = ($assertion instanceof EncryptedAssertion)
254
                ? $this->decryptElement($assertion)
255
                : $assertion;
256
257
            // Verify the signature on the assertions (if any)
258
            $verifiedAssertion = $this->verifyElementSignature($decryptedAssertion);
0 ignored issues
show
Bug introduced by
It seems like $decryptedAssertion can also be of type SimpleSAML\XMLSecurity\X...yptableElementInterface; however, parameter $element of SimpleSAML\SAML2\Entity\...erifyElementSignature() does only seem to accept SimpleSAML\XMLSecurity\XML\SignedElementInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

258
            $verifiedAssertion = $this->verifyElementSignature(/** @scrutinizer ignore-type */ $decryptedAssertion);
Loading history...
259
260
            // Decrypt the NameID and replace it inside the assertion's Subject
261
            $nameID = $verifiedAssertion->getSubject()?->getIdentifier();
262
263
            if ($nameID instanceof EncryptedID) {
264
                $decryptedNameID = $this->decryptElement($nameID);
265
                $subject = new Subject($decryptedNameID, $verifiedAssertion->getSubjectConfirmation());
0 ignored issues
show
Bug introduced by
The method getSubjectConfirmation() does not exist on SimpleSAML\SAML2\XML\saml\Assertion. Did you maybe mean getSubject()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

265
                $subject = new Subject($decryptedNameID, $verifiedAssertion->/** @scrutinizer ignore-call */ getSubjectConfirmation());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
266
            } else {
267
                $subject = $verifiedAssertion->getSubject();
268
            }
269
270
            // Decrypt any occurrences of EncryptedAttribute and replace them inside the assertion's AttributeStatement
271
            $statements = $verifiedAssertion->getStatements();
272
            foreach ($verifiedAssertion->getStatements() as $j => $statement) {
273
                if ($statement instanceof AttributeStatement) {
274
                    $attributes = $statement->getAttributes();
275
                    if ($statement->hasEncryptedAttributes()) {
276
                        foreach ($statement->getEncryptedAttributes() as $encryptedAttribute) {
277
                            $attributes[] = $this->decryptElement($encryptedAttribute);
278
                        }
279
                    }
280
281
                    $statements[$j] = new AttributeStatement($attributes);
282
                }
283
            }
284
285
            // Rebuild the Assertion
286
            $verifiedAssertions[] = new Assertion(
287
                $verifiedAssertion->getIssuer(),
288
                $verifiedAssertion->getIssueInstant(),
289
                $verifiedAssertion->getID(),
290
                $subject,
291
                $verifiedAssertion->getConditions(),
292
                $statements,
293
            );
294
        }
295
296
        return $verifiedAssertions;
297
    }
298
299
300
    /**
301
     * Decrypt the given element using the decryption keys provided to us.
302
     *
303
     * @param \SimpleSAML\XMLSecurity\XML\EncryptedElementInterface $element
304
     * @return \SimpleSAML\XMLSecurity\EncryptableElementInterface
0 ignored issues
show
Bug introduced by
The type SimpleSAML\XMLSecurity\EncryptableElementInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
305
     *
306
     * @throws \SimpleSAML\SAML2\Exception\RuntimeException if none of the keys could be used to decrypt the element
307
     */
308
    protected function decryptElement(EncryptedElementInterface $element): EncryptableElementInterface
309
    {
310
        $factory = $this->spMetadata->getEncryptionAlgorithmFactory();
311
312
        $encryptionAlgorithm = ($factory instanceof EncryptionAlgorithmFactory)
313
            ? $element->getEncryptedData()->getEncryptionMethod()
314
            : $element->getEncryptedKey()->getEncryptionMethod();
315
316
        foreach ($this->spMetadata->getDecriptionKeys() as $decryptionKey) {
0 ignored issues
show
Bug introduced by
The method getDecriptionKeys() does not exist on SimpleSAML\SAML2\Metadata\ServiceProvider. Did you maybe mean getDecryptionKeys()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

316
        foreach ($this->spMetadata->/** @scrutinizer ignore-call */ getDecriptionKeys() as $decryptionKey) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
317
            $decryptor = $factory->getAlgorithm($encryptionAlgorithm, $decryptionKey);
0 ignored issues
show
Bug introduced by
It seems like $encryptionAlgorithm can also be of type null; however, parameter $algId of SimpleSAML\XMLSecurity\A...Factory::getAlgorithm() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

317
            $decryptor = $factory->getAlgorithm(/** @scrutinizer ignore-type */ $encryptionAlgorithm, $decryptionKey);
Loading history...
Bug introduced by
It seems like $encryptionAlgorithm can also be of type null; however, parameter $algId of SimpleSAML\XMLSecurity\A...Factory::getAlgorithm() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

317
            $decryptor = $factory->getAlgorithm(/** @scrutinizer ignore-type */ $encryptionAlgorithm, $decryptionKey);
Loading history...
318
            try {
319
                return $element->decrypt($decryptor);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $element->decrypt($decryptor) returns the type SimpleSAML\XML\ElementInterface which is incompatible with the type-hinted return SimpleSAML\XMLSecurity\X...yptableElementInterface.
Loading history...
320
            } catch (Exception $e) {
321
                continue;
322
            }
323
        }
324
325
        throw new RuntimeException(sprintf(
326
            'Unable to decrypt %s with any of the available keys.',
327
            $element::class,
328
        ));
329
    }
330
331
332
    /**
333
     * Verify the signature of an element using the available validation keys.
334
     *
335
     * @param \SimpleSAML\XMLSecurity\XML\SignedElementInterface $element
336
     * @return \SimpleSAML\XMLSecurity\XML\SignableElementInterface The validated element.
337
     *
338
     * @throws \SimpleSAML\XMLSecurity\Exception\SignatureVerificationFailedException
339
     */
340
    protected function verifyElementSignature(SignedElementInterface $element): SignableElementInterface
341
    {
342
        $factory = $this->spMetadata->getSignatureAlgorithmFactory();
343
        $signatureAlgorithm = $element->getSignature()->getSignedInfo()->getSignatureMethod()->getAlgorithm();
344
345
        foreach ($this->idpMetadata->getValidatingKeys() as $validatingKey) {
0 ignored issues
show
Bug introduced by
The method getValidatingKeys() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

345
        foreach ($this->idpMetadata->/** @scrutinizer ignore-call */ getValidatingKeys() as $validatingKey) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
346
            $verifier = $factory->getAlgorithm($signatureAlgorithm, $validatingKey);
347
348
            try {
349
                return $element->verify($verifier);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $element->verify($verifier) returns the type SimpleSAML\XMLSecurity\XML\SignedElementInterface which is incompatible with the type-hinted return SimpleSAML\XMLSecurity\X...ignableElementInterface.
Loading history...
350
            } catch (SignatureVerificationFailedException $e) {
351
                continue;
352
            }
353
        }
354
355
        throw new SignatureVerificationFailedException();
356
    }
357
}
358