NegotiateController   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 170
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 12
eloc 61
c 1
b 0
f 0
dl 0
loc 170
rs 10

7 Methods

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