Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 56 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
RedirectingLoginHookHandler | |
0.00% |
0 / 56 |
|
0.00% |
0 / 4 |
240 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
onPostLoginRedirect | |
0.00% |
0 / 43 |
|
0.00% |
0 / 1 |
132 | |||
onAuthPreserveQueryParams | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
2 | |||
onAuthChangeFormFields | |
0.00% |
0 / 3 |
|
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 | |
21 | namespace MediaWiki\Extension\CentralAuth\Hooks\Handlers; |
22 | |
23 | use ErrorPageError; |
24 | use LogicException; |
25 | use MediaWiki\Auth\Hook\AuthPreserveQueryParamsHook; |
26 | use MediaWiki\Context\RequestContext; |
27 | use MediaWiki\Extension\CentralAuth\CentralAuthRedirectingPrimaryAuthenticationProvider; |
28 | use MediaWiki\Extension\CentralAuth\CentralAuthTokenManager; |
29 | use MediaWiki\Extension\CentralAuth\SharedDomainUtils; |
30 | use MediaWiki\Extension\CentralAuth\User\CentralAuthUser; |
31 | use MediaWiki\Hook\PostLoginRedirectHook; |
32 | use MediaWiki\Logger\LoggerFactory; |
33 | use MediaWiki\SpecialPage\Hook\AuthChangeFormFieldsHook; |
34 | |
35 | /** |
36 | * Hook handler for hooks related to SUL3 login. |
37 | * |
38 | * @see CentralAuthRedirectingPrimaryAuthenticationProvider |
39 | */ |
40 | class RedirectingLoginHookHandler implements |
41 | PostLoginRedirectHook, |
42 | AuthPreserveQueryParamsHook, |
43 | AuthChangeFormFieldsHook |
44 | { |
45 | |
46 | private CentralAuthTokenManager $tokenManager; |
47 | private SharedDomainUtils $sharedDomainUtils; |
48 | |
49 | public function __construct( |
50 | CentralAuthTokenManager $tokenManager, |
51 | SharedDomainUtils $sharedDomainUtils |
52 | ) { |
53 | $this->tokenManager = $tokenManager; |
54 | $this->sharedDomainUtils = $sharedDomainUtils; |
55 | } |
56 | |
57 | /** |
58 | * After a SUL3 login on the shared login domain, redirect the user back to the |
59 | * original wiki and indicate the result of the login. |
60 | * @inheritDoc |
61 | */ |
62 | public function onPostLoginRedirect( &$returnTo, &$returnToQuery, &$type ) { |
63 | $context = RequestContext::getMain(); |
64 | $request = $context->getRequest(); |
65 | if ( |
66 | !$this->sharedDomainUtils->isSharedDomain() |
67 | || !$this->sharedDomainUtils->isSul3Enabled( $request ) |
68 | ) { |
69 | return; |
70 | } |
71 | |
72 | $token = $request->getRawVal( 'centralauthLoginToken' ); |
73 | $inputData = null; |
74 | if ( $token ) { |
75 | $inputData = $this->tokenManager->detokenizeAndDelete( |
76 | $token, |
77 | CentralAuthRedirectingPrimaryAuthenticationProvider::START_TOKEN_KEY_PREFIX |
78 | ); |
79 | } |
80 | if ( !$inputData ) { |
81 | LoggerFactory::getInstance( 'authevents' ) |
82 | ->warning( 'Authentication request with bad token', [ |
83 | 'event' => ( $type === 'signup' ) ? 'accountcreation' : 'login', |
84 | 'successful' => false, |
85 | 'extension' => 'CentralAuth', |
86 | 'accountType' => $context->getUser()->isNamed() ? 'named' : 'temp', |
87 | 'status' => 'badtoken' |
88 | ] ); |
89 | throw new ErrorPageError( 'centralauth-error-badtoken', 'centralauth-error-badtoken' ); |
90 | } |
91 | $returnUrl = $inputData['returnUrl']; |
92 | |
93 | if ( !$context->getUser()->isRegistered() ) { |
94 | throw new LogicException( 'Unregistered user at end of login' ); |
95 | } |
96 | $centralUser = CentralAuthUser::getInstanceByName( $context->getUser()->getName() ); |
97 | if ( !$centralUser->exists() ) { |
98 | $centralUser = CentralAuthUser::getPrimaryInstanceByName( $context->getUser()->getName() ); |
99 | } |
100 | if ( !$centralUser->exists() || !$centralUser->isAttached() ) { |
101 | throw new LogicException( 'Unattached user at end of login' ); |
102 | } |
103 | |
104 | $outputData = $inputData + [ |
105 | 'username' => $centralUser->getName(), |
106 | 'userId' => $centralUser->getId(), |
107 | 'rememberMe' => $request->getSession()->shouldRememberUser(), |
108 | ]; |
109 | $token = $this->tokenManager->tokenize( |
110 | $outputData, |
111 | CentralAuthRedirectingPrimaryAuthenticationProvider::COMPLETE_TOKEN_KEY_PREFIX |
112 | ); |
113 | |
114 | // We have a return URL from the login wiki, we're fine. |
115 | $url = wfAppendQuery( $returnUrl, [ 'centralauthLoginToken' => $token ] ); |
116 | $context->getOutput()->redirect( $url ); |
117 | $type = 'success'; |
118 | |
119 | return true; |
120 | } |
121 | |
122 | public function onAuthPreserveQueryParams( array &$params, array $options ) { |
123 | $context = RequestContext::getMain(); |
124 | $request = $context->getRequest(); |
125 | |
126 | $params += [ |
127 | 'centralauthLoginToken' => $request->getRawVal( 'centralauthLoginToken' ), |
128 | 'wikiid' => $request->getRawVal( 'wikiid' ), |
129 | 'usesul3' => $request->getRawVal( 'usesul3' ), |
130 | 'useformat' => $request->getRawVal( 'useformat' ), |
131 | ]; |
132 | } |
133 | |
134 | /** |
135 | * Move the redirect button below the normal login button. Displaying the normal login form |
136 | * is prevented elsewhere, but just in case, if that fails, avoid this button being the |
137 | * default form control that gets submitted when the user types into the username/password |
138 | * field and presses Enter. |
139 | * @inheritDoc |
140 | */ |
141 | public function onAuthChangeFormFields( $requests, $fieldInfo, &$formDescriptor, $action ) { |
142 | $formFieldName = CentralAuthRedirectingPrimaryAuthenticationProvider::NON_LOGIN_WIKI_BUTTONREQUEST_NAME; |
143 | if ( isset( $formDescriptor[$formFieldName] ) ) { |
144 | $formDescriptor[$formFieldName]['weight'] = 101; |
145 | } |
146 | } |
147 | } |