NegotiateController::enable()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 13
nc 1
nop 0
dl 0
loc 19
rs 9.8333
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\Module\negotiateext\Controller;
6
7
use Exception;
8
use SimpleSAML\Auth;
9
use SimpleSAML\Configuration;
10
use SimpleSAML\Error;
11
use SimpleSAML\HTTP\RunnableResponse;
12
use SimpleSAML\Logger;
13
use SimpleSAML\Metadata\MetaDataStorageHandler;
14
use SimpleSAML\Module;
15
use SimpleSAML\Module\negotiateext\Auth\Source\Negotiate;
16
use SimpleSAML\Session;
17
use SimpleSAML\XHTML\Template;
18
use Symfony\Component\HttpFoundation\{Cookie, RedirectResponse, Request};
19
20
/**
21
 * Controller class for the negotiate module.
22
 *
23
 * This class serves the different views available in the module.
24
 *
25
 * @package SimpleSAML\Module\negotiate
26
 */
27
class NegotiateController
28
{
29
    /** @var \SimpleSAML\Configuration */
30
    protected Configuration $config;
31
32
    /** @var \SimpleSAML\Session */
33
    protected Session $session;
34
35
36
    /**
37
     * Controller constructor.
38
     *
39
     * It initializes the global configuration and session for the controllers implemented here.
40
     *
41
     * @param \SimpleSAML\Configuration              $config The configuration to use by the controllers.
42
     * @param \SimpleSAML\Session                    $session The session to use by the controllers.
43
     *
44
     * @throws \Exception
45
     */
46
    public function __construct(
47
        Configuration $config,
48
        Session $session,
49
    ) {
50
        $this->config = $config;
51
        $this->session = $session;
52
    }
53
54
55
    /**
56
     * Perform auth.
57
     *
58
     * @return \SimpleSAML\HTTP\RunnableResponse
59
     */
60
    public function auth(): RunnableResponse
61
    {
62
        return new RunnableResponse([Negotiate::class, 'external']);
63
    }
64
65
66
    /**
67
     * Process authentication error
68
     *
69
     * @param Request $request The request that lead to this retry operation.
70
     * @return \Symfony\Component\HttpFoundation\RedirectResponse
71
     */
72
    public function error(Request $request): RedirectResponse
73
    {
74
        $query = $request->server->get('REDIRECT_QUERY_STRING');
75
        $url = $request->server->get('REDIRECT_URL');
76
77
        $authState = $request->query->get('AuthState', null);
78
        if ($authState === null) {
79
            throw new Error\BadRequest('Missing "AuthState" parameter.');
80
        }
81
82
        Auth\State::loadState($authState, Negotiate::STAGEID);
83
84
        $url = str_replace('/auth', '/backend', $url . '?' . $query);
85
        return new RedirectResponse($url);
86
    }
87
88
89
    /**
90
     * Show enable.
91
     *
92
     * @return \SimpleSAML\XHTML\Template
93
     */
94
    public function enable(): Template
95
    {
96
        $this->session->setData('negotiateext:disable', 'session', false, 86400); // 24*60*60=86400
97
98
        $cookie = new Cookie(
99
            'NEGOTIATE_AUTOLOGIN_DISABLE_PERMANENT',
100
            null, // value
101
            mktime(0, 0, 0, 1, 1, 2038), // expire
102
            '/', // path
103
            '', // domain
104
            true, // secure
105
            true, // httponly
106
        );
107
108
        $t = new Template($this->config, 'negotiateext:enable.twig');
109
        $t->headers->setCookie($cookie);
110
        $t->data['url'] = Module::getModuleURL('negotiateext/disable');
111
112
        return $t;
113
    }
114
115
116
    /**
117
     * Show disable.
118
     *
119
     * @return \SimpleSAML\XHTML\Template
120
     */
121
    public function disable(): Template
122
    {
123
        $this->session->setData('negotiateext:disable', 'session', false, 86400); //24*60*60=86400
124
125
        $cookie = new Cookie(
126
            'NEGOTIATE_AUTOLOGIN_DISABLE_PERMANENT',
127
            'true', // value
128
            mktime(0, 0, 0, 1, 1, 2038), // expire
129
            '/', // path
130
            '', // domain
131
            true, // secure
132
            true, // httponly
133
        );
134
135
        $t = new Template($this->config, 'negotiateext:disable.twig');
136
        $t->headers->setCookie($cookie);
137
        $t->data['url'] = Module::getModuleURL('negotiateext/enable');
138
139
        return $t;
140
    }
141
142
143
    /**
144
     * Show retry
145
     *
146
     * @param Request $request The request that lead to this retry operation.
147
     * @return \SimpleSAML\HTTP\RunnableResponse
148
     */
149
    public function retry(Request $request): RunnableResponse
150
    {
151
        $authState = $request->query->get('AuthState', null);
152
        if ($authState === null) {
153
            throw new Error\BadRequest('Missing required AuthState query parameter.');
154
        }
155
156
        /** @psalm-var array $state */
157
        $state = Auth\State::loadState($authState, Negotiate::STAGEID);
158
159
        $metadata = MetaDataStorageHandler::getMetadataHandler();
160
        $idpid = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted', 'metaindex');
161
        $idpmeta = $metadata->getMetaData($idpid, 'saml20-idp-hosted');
162
163
        if (isset($idpmeta['auth'])) {
164
            $source = Auth\Source::getById($idpmeta['auth']);
165
            if ($source === null) {
166
                throw new Error\BadRequest('Invalid AuthId "' . $idpmeta['auth'] . '" - not found.');
167
            }
168
169
            $this->session->setData('negotiateext:disable', 'session', false, 86400); //24*60*60=86400
170
            Logger::debug('Negotiate(retry) - session enabled, retrying.');
171
172
            return new RunnableResponse([$source, 'authenticate'], [&$state]);
173
        }
174
        throw new Exception('Negotiate - retry - no "auth" parameter found in IdP metadata.');
175
    }
176
177
178
    /**
179
     * Show fallback
180
     *
181
     * @param Request $request The request that lead to this retry operation.
182
     * @return \SimpleSAML\HTTP\RunnableResponse
183
     */
184
    public function fallback(Request $request): RunnableResponse
185
    {
186
        $authState = $request->query->get('AuthState', null);
187
        if ($authState === null) {
188
            throw new Error\BadRequest('Missing required AuthState query parameter.');
189
        }
190
191
        /** @psalm-var array $state */
192
        $state = Auth\State::loadState($authState, Negotiate::STAGEID);
193
194
        Logger::debug('backend - fallback: ' . $state['LogoutState']['negotiateext:backend']);
195
196
        return new RunnableResponse([Negotiate::class, 'fallback'], [&$state]);
197
    }
198
}
199