Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
RedirectingLoginHookHandler
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 4
110
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 onPostLoginRedirect
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
42
 onAuthPreserveQueryParams
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 onAuthChangeFormFields
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21namespace MediaWiki\Extension\CentralAuth\Hooks\Handlers;
22
23use ErrorPageError;
24use MediaWiki\Auth\Hook\AuthPreserveQueryParamsHook;
25use MediaWiki\Context\RequestContext;
26use MediaWiki\Extension\CentralAuth\CentralAuthRedirectingPrimaryAuthenticationProvider;
27use MediaWiki\Extension\CentralAuth\CentralAuthSessionManager;
28use MediaWiki\Extension\CentralAuth\CentralAuthUtilityService;
29use MediaWiki\Extension\CentralAuth\SharedDomainUtils;
30use MediaWiki\Hook\PostLoginRedirectHook;
31use MediaWiki\SpecialPage\Hook\AuthChangeFormFieldsHook;
32
33class RedirectingLoginHookHandler implements
34    PostLoginRedirectHook,
35    AuthPreserveQueryParamsHook,
36    AuthChangeFormFieldsHook
37{
38    /**
39     * @internal For use by CentralAuth only.
40     * @var string Storage key prefix for the token when continuing the login
41     *    in the local wiki.
42     */
43    public const LOGIN_CONTINUE_USERNAME_KEY_PREFIX = 'centralauth-post-login-redirect-username';
44
45    private CentralAuthSessionManager $sessionManager;
46    private CentralAuthUtilityService $caUtilityService;
47    private SharedDomainUtils $sharedDomainUtils;
48
49    public function __construct(
50        CentralAuthSessionManager $sessionManager,
51        CentralAuthUtilityService $utility,
52        SharedDomainUtils $sharedDomainUtils
53    ) {
54        $this->sessionManager = $sessionManager;
55        $this->caUtilityService = $utility;
56        $this->sharedDomainUtils = $sharedDomainUtils;
57    }
58
59    /**
60     * After a SUL3 login on the shared login domain, redirect the user back to the
61     * original wiki and indicate the result of the login.
62     * @inheritDoc
63     */
64    public function onPostLoginRedirect( &$returnTo, &$returnToQuery, &$type ) {
65        $context = RequestContext::getMain();
66        $request = $context->getRequest();
67        if (
68            !$this->sharedDomainUtils->isSharedDomain()
69            || !$this->sharedDomainUtils->isSul3Enabled( $request )
70        ) {
71            return;
72        }
73
74        $returnUrlToken = $request->getRawVal( 'returnUrlToken' );
75        if ( $returnUrlToken ) {
76            $returnUrl = $this->caUtilityService->detokenize(
77                $returnUrlToken,
78                CentralAuthRedirectingPrimaryAuthenticationProvider::RETURN_URL_TOKEN_KEY_PREFIX,
79                $this->sessionManager
80            );
81        } else {
82            $returnUrl = false;
83        }
84        if ( !$returnUrl ) {
85            throw new ErrorPageError( 'centralauth-error-badtoken', 'centralauth-error-badtoken' );
86        }
87
88        if ( !$context->getUser()->isRegistered() ) {
89            throw new \LogicException( 'This account is not a registered user' );
90        }
91
92        $userToken = $this->caUtilityService->tokenize(
93            $context->getUser()->getName(),
94            self::LOGIN_CONTINUE_USERNAME_KEY_PREFIX,
95            $this->sessionManager
96        );
97        $url = wfAppendQuery( $returnUrl, [ 'token' => $userToken ] );
98
99        // We have a return URL from the login wiki, we're fine.
100        $context->getOutput()->redirect( $url );
101        $type = 'success';
102
103        return true;
104    }
105
106    public function onAuthPreserveQueryParams( array &$params, array $options ) {
107        $context = RequestContext::getMain();
108        $request = $context->getRequest();
109
110        $params += [
111            'returnUrlToken' => $request->getRawVal( 'returnUrlToken' ),
112            'wikiid' => $request->getRawVal( 'wikiid' ),
113            'usesul3' => $request->getRawVal( 'usesul3' ),
114        ];
115    }
116
117    /**
118     * Move the redirect button below the normal login button. Displaying the normal login form
119     * is prevented elsewhere, but just in case, if that fails, avoid this button being the
120     * default form control that gets submitted when the user types into the username/password
121     * field and presses Enter.
122     * @inheritDoc
123     */
124    public function onAuthChangeFormFields( $requests, $fieldInfo, &$formDescriptor, $action ) {
125        $formFieldName = CentralAuthRedirectingPrimaryAuthenticationProvider::NON_LOGIN_WIKI_BUTTONREQUEST_NAME;
126        if ( isset( $formDescriptor[$formFieldName] ) ) {
127            $formDescriptor[$formFieldName]['weight'] = 101;
128        }
129    }
130}