SOAP::getOutputToSend()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 25
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 13
nc 3
nop 1
dl 0
loc 25
rs 9.8333
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\Binding;
6
7
use Exception;
8
use Nyholm\Psr7\Response;
9
use Psr\Http\Message\ResponseInterface;
10
use Psr\Http\Message\ServerRequestInterface;
11
use SimpleSAML\SAML2\Binding;
12
use SimpleSAML\SAML2\Exception\Protocol\UnsupportedBindingException;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\Excepti...pportedBindingException 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...
13
use SimpleSAML\SAML2\Type\SAMLAnyURIValue;
14
use SimpleSAML\SAML2\Utils;
15
use SimpleSAML\SAML2\XML\ecp\RequestAuthenticated;
16
use SimpleSAML\SAML2\XML\ecp\Response as ECPResponse;
17
use SimpleSAML\SAML2\XML\samlp\AbstractMessage;
18
use SimpleSAML\SAML2\XML\samlp\MessageFactory;
19
use SimpleSAML\SAML2\XML\samlp\Response as SAML2_Response;
20
use SimpleSAML\SOAP11\Type\MustUnderstandValue;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SOAP11\Type\MustUnderstandValue 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...
21
use SimpleSAML\SOAP11\Utils\XPath;
22
use SimpleSAML\SOAP11\XML\Body;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SOAP11\XML\Body 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...
23
use SimpleSAML\SOAP11\XML\Envelope;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SOAP11\XML\Envelope 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...
24
use SimpleSAML\SOAP11\XML\Header;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SOAP11\XML\Header 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...
25
use SimpleSAML\XML\DOMDocumentFactory;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\XML\DOMDocumentFactory 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...
26
27
use function file_get_contents;
28
29
/**
30
 * Class which implements the SOAP binding.
31
 *
32
 * @package simplesamlphp/saml2
33
 */
34
class SOAP extends Binding implements SynchronousBindingInterface
35
{
36
    /**
37
     * @param \SimpleSAML\SAML2\XML\samlp\AbstractMessage $message
38
     * @return string|false The XML or false on error
39
     *
40
     * @throws \Exception
41
     */
42
    public function getOutputToSend(AbstractMessage $message): string|false
43
    {
44
        $header = new Header();
45
46
        // In the Artifact Resolution profile, this will be an ArtifactResolve
47
        // containing another message (e.g. a Response), however in the ECP
48
        // profile, this is the Response itself.
49
        if ($message instanceof SAML2_Response) {
50
            $requestAuthenticated = new RequestAuthenticated(
51
                MustUnderstandValue::fromBoolean(true),
52
            );
53
54
            $destination = $this->destination ?: $message->getDestination()?->getValue();
55
            if ($destination === null) {
56
                throw new Exception('No destination available for SOAP message.');
57
            }
58
            $response = new ECPResponse(SAMLAnyURIValue::fromString($destination));
59
            $header = new Header([$requestAuthenticated, $response]);
60
        }
61
62
        $env = new Envelope(
63
            new Body([$message]),
64
            $header,
65
        );
66
        return $env->toXML()->ownerDocument?->saveXML();
67
    }
68
69
70
    /**
71
     * Send a SAML 2 message using the SOAP binding.
72
     *
73
     * @param \SimpleSAML\SAML2\XML\samlp\AbstractMessage $message The message we should send.
74
     * @return \Psr\Http\Message\ResponseInterface
75
     */
76
    public function send(AbstractMessage $message): ResponseInterface
77
    {
78
        $xml = $this->getOutputToSend($message);
79
        Utils::getContainer()->debugMessage($xml, 'out');
0 ignored issues
show
Bug introduced by
It seems like $xml can also be of type false; however, parameter $message of SimpleSAML\SAML2\Compat\...ntainer::debugMessage() does only seem to accept DOMElement|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

79
        Utils::getContainer()->debugMessage(/** @scrutinizer ignore-type */ $xml, 'out');
Loading history...
80
81
        return new Response(200, ['Content-Type' => 'text/xml'], $xml);
82
    }
83
84
85
    /**
86
     * Receive a SAML 2 message sent using the HTTP-POST binding.
87
     *
88
     * @param \Psr\Http\Message\ServerRequestInterface $request
89
     * @return \SimpleSAML\SAML2\XML\samlp\AbstractMessage The received message.
90
     *
91
     * @throws \Exception If unable to receive the message
92
     */
93
    public function receive(/** @scrutinizer ignore-unused */ServerRequestInterface $request): AbstractMessage
94
    {
95
        $postText = $this->getInputStream();
96
97
        if (empty($postText)) {
98
            throw new UnsupportedBindingException('Invalid message received at AssertionConsumerService endpoint.');
99
        }
100
101
        $document = DOMDocumentFactory::fromString($postText);
102
        /** @var \DOMNode $xml */
103
        $xml = $document->firstChild;
104
        Utils::getContainer()->debugMessage($document->documentElement, 'in');
105
106
        $xpCache = XPath::getXPath($document->documentElement);
107
        /** @var \DOMElement[] $results */
108
        $results = XPath::xpQuery($xml, '/SOAP-ENV:Envelope/SOAP-ENV:Body/*[1]', $xpCache);
109
110
        return MessageFactory::fromXML($results[0]);
111
    }
112
113
114
    /**
115
     * @return string|false
116
     */
117
    protected function getInputStream(): string|false
118
    {
119
        return file_get_contents('php://input');
120
    }
121
}
122