Passed
Branch master (b017eb)
by Tim
01:58
created

AttributeServer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\Module\exampleattributeserver\Controller;
6
7
use SAML2\Assertion;
8
use SAML2\AttributeQuery;
9
use SAML2\Binding;
10
use SAML2\Constants;
11
use SAML2\HTTPPost;
12
use SAML2\Response;
13
use SAML2\XML\saml\Issuer;
14
use SAML2\XML\saml\SubjectConfirmation;
15
use SAML2\XML\saml\SubjectConfirmationData;
16
use SimpleSAML\Configuration;
17
use SimpleSAML\Error;
18
use SimpleSAML\HTTP\RunnableResponse;
19
use SimpleSAML\Logger;
20
use SimpleSAML\Session;
21
use SimpleSAML\Metadata\MetaDataStorageHandler;
22
use SimpleSAML\Module\saml\Message;
23
use SimpleSAML\XHTML\Template;
24
use Symfony\Component\HttpFoundation\Request;
25
26
/**
27
 * Controller class for the exampleattributeserver module.
28
 *
29
 * This class serves the attribute server available in the module.
30
 *
31
 * @package SimpleSAML\Module\exampleattributeserver
32
 */
33
class AttributeServer
34
{
35
    /** @var \SimpleSAML\Configuration */
36
    protected Configuration $config;
37
38
    /** @var \SimpleSAML\Metadata\MetaDataStorageHandler|null */
39
    protected ?MetaDataStorageHandler $metadataHandler = null;
40
41
    /** @var \SimpleSAML\Session */
42
    protected Session $session;
43
44
45
    /**
46
     * ConfigController constructor.
47
     *
48
     * @param \SimpleSAML\Configuration $config The configuration to use.
49
     * @param \SimpleSAML\Session $session The current user session.
50
     */
51
    public function __construct(Configuration $config, Session $session)
52
    {
53
        $this->config = $config;
54
        $this->session = $session;
55
    }
56
57
58
    /**
59
     * Inject the \SimpleSAML\Metadata\MetaDataStorageHandler dependency.
60
     *
61
     * @param \SimpleSAML\Metadata\MetaDataStorageHandler $handler
62
     */
63
    public function setMetadataStorageHandler(MetaDataStorageHandler $handler): void
64
    {
65
        $this->metadataHandler = $handler;
66
    }
67
68
69
    /**
70
     * @param \Symfony\Component\HttpFoundation\Request $request The current request.
71
     *
72
     * @return \SimpleSAML\HTTP\RunnableResponse
73
     * @throws \SimpleSAML\Error\BadRequest
74
     */
75
    public function main(/** @scrutinizer ignore-unused */ Request $request): RunnableResponse
76
    {
77
        $binding = Binding::getCurrentBinding();
78
        $query = $binding->receive();
79
        if (!($query instanceof AttributeQuery)) {
80
            throw new Error\BadRequest('Invalid message received to AttributeQuery endpoint.');
81
        }
82
83
        $idpEntityId = $this->metadataHandler->getMetaDataCurrentEntityID('saml20-idp-hosted');
0 ignored issues
show
Bug introduced by
The method getMetaDataCurrentEntityID() 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

83
        /** @scrutinizer ignore-call */ 
84
        $idpEntityId = $this->metadataHandler->getMetaDataCurrentEntityID('saml20-idp-hosted');

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...
84
85
        $issuer = $query->getIssuer();
86
        if ($issuer === null) {
87
            throw new Error\BadRequest('Missing <saml:Issuer> in <samlp:AttributeQuery>.');
88
        } else {
89
            $spEntityId = $issuer->getValue();
90
            if ($spEntityId === '') {
91
                throw new Error\BadRequest('Empty <saml:Issuer> in <samlp:AttributeQuery>.');
92
            }
93
        }
94
95
        $idpMetadata = $this->metadataHandler->getMetaDataConfig($idpEntityId, 'saml20-idp-hosted');
96
        $spMetadata = $this->metadataHandler->getMetaDataConfig($spEntityId, 'saml20-sp-remote');
97
98
        // The endpoint we should deliver the message to
99
        $endpoint = $spMetadata->getString('testAttributeEndpoint');
100
101
        // The attributes we will return
102
        $attributes = [
103
            'name' => ['value1', 'value2', 'value3'],
104
            'test' => ['test'],
105
        ];
106
107
        // The name format of the attributes
108
        $attributeNameFormat = Constants::NAMEFORMAT_UNSPECIFIED;
109
110
        // Determine which attributes we will return
111
        $returnAttributes = array_keys($query->getAttributes());
112
        if (count($returnAttributes) === 0) {
113
            Logger::debug('No attributes requested - return all attributes.');
114
            $returnAttributes = $attributes;
115
        } elseif ($query->getAttributeNameFormat() !== $attributeNameFormat) {
116
            Logger::debug('Requested attributes with wrong NameFormat - no attributes returned.');
117
            $returnAttributes = [];
118
        } else {
119
            /** @var array $values */
120
            foreach ($returnAttributes as $name => $values) {
121
                if (!array_key_exists($name, $attributes)) {
122
                    // We don't have this attribute
123
                    unset($returnAttributes[$name]);
124
                    continue;
125
                }
126
                if (count($values) === 0) {
127
                    // Return all attributes
128
                    $returnAttributes[$name] = $attributes[$name];
129
                    continue;
130
                }
131
132
                // Filter which attribute values we should return
133
                $returnAttributes[$name] = array_intersect($values, $attributes[$name]);
134
            }
135
        }
136
137
        // $returnAttributes contains the attributes we should return. Send them
138
        $issuer = new Issuer();
139
        $issuer->setValue($idpEntityId);
140
141
        $assertion = new Assertion();
142
        $assertion->setIssuer($issuer);
143
        $assertion->setNameId($query->getNameId());
144
        $assertion->setNotBefore(time());
145
        $assertion->setNotOnOrAfter(time() + 300); // 60*5 = 5min
146
        $assertion->setValidAudiences([$spEntityId]);
147
        $assertion->setAttributes($returnAttributes);
148
        $assertion->setAttributeNameFormat($attributeNameFormat);
149
150
        $sc = new SubjectConfirmation();
151
        $sc->setMethod(Constants::CM_BEARER);
152
153
        $scd = new SubjectConfirmationData();
154
        $scd->setNotOnOrAfter(time() + 300); // 60*5 = 5min
155
        $scd->setRecipient($endpoint);
156
        $scd->setInResponseTo($query->getId());
157
        $sc->setSubjectConfirmationData($scd);
158
        $assertion->setSubjectConfirmation([$sc]);
159
160
        Message::addSign($idpMetadata, $spMetadata, $assertion);
161
162
        $response = new Response();
163
        $response->setRelayState($query->getRelayState());
164
        $response->setDestination($endpoint);
165
        $response->setIssuer($issuer);
166
        $response->setInResponseTo($query->getId());
167
        $response->setAssertions([$assertion]);
168
        Message::addSign($idpMetadata, $spMetadata, $response);
169
170
        return new RunnableResponse([new HTTPPost(), 'send'], [$response]);
171
    }
172
}
173