18 AuthManager::ACTION_LOGIN, AuthManager::ACTION_LOGIN_CONTINUE,
19 AuthManager::ACTION_CREATE, AuthManager::ACTION_CREATE_CONTINUE,
20 AuthManager::ACTION_LINK, AuthManager::ACTION_LINK_CONTINUE,
21 AuthManager::ACTION_CHANGE, AuthManager::ACTION_REMOVE, AuthManager::ACTION_UNLINK,
64 return $this->savedRequest ?: $this->
getContext()->getRequest();
77 if ( $wasPosted ===
null ) {
108 $authManager = AuthManager::singleton();
109 $key =
'AuthManagerSpecialPage:return:' . $this->
getName();
116 $authData = array_diff_key( $this->
getRequest()->getValues(),
117 $preservedParams, [
'title' => 1 ] );
118 $authManager->setAuthenticationSessionData( $key, $authData );
125 $authData = $authManager->getAuthenticationSessionData( $key );
127 $authManager->removeAuthenticationSessionData( $key );
128 $this->isReturn =
true;
146 $authManager = AuthManager::singleton();
148 $key =
'AuthManagerSpecialPage:reauth:' . $this->
getName();
151 if ( $securityLevel ) {
152 $securityStatus = AuthManager::singleton()
153 ->securitySensitiveOperationStatus( $securityLevel );
154 if ( $securityStatus === AuthManager::SEC_REAUTH ) {
155 $queryParams = array_diff_key(
$request->getQueryValues(), [
'title' =>
true ] );
160 $key = $key .
':' . $uniqueId;
162 $queryParams = [
'authUniqueId' => $uniqueId ] + $queryParams;
163 $authData = array_diff_key(
$request->getValues(),
165 $authManager->setAuthenticationSessionData( $key, $authData );
169 $url =
$title->getFullURL( [
170 'returnto' => $this->
getFullTitle()->getPrefixedDBkey(),
172 'force' => $securityLevel,
177 } elseif ( $securityStatus !== AuthManager::SEC_OK ) {
178 throw new ErrorPageError(
'cannotauth-not-allowed-title',
'cannotauth-not-allowed' );
182 $uniqueId =
$request->getVal(
'authUniqueId' );
184 $key = $key .
':' . $uniqueId;
185 $authData = $authManager->getAuthenticationSessionData( $key );
187 $authManager->removeAuthenticationSessionData( $key );
236 !$reset && $this->subPage ===
$subPage && $this->authAction
245 if ( !in_array( $this->authAction, static::$allowedActions,
true ) ) {
249 if ( in_array( $continueAction, static::$allowedActions,
true ) ) {
250 $this->authAction = $continueAction;
255 $allReqs = AuthManager::singleton()->getAuthenticationRequests(
256 $this->authAction, $this->
getUser() );
257 $this->authRequests = array_filter( $allReqs,
function (
$req )
use (
$subPage ) {
267 return in_array( $this->authAction, [
268 AuthManager::ACTION_LOGIN_CONTINUE,
269 AuthManager::ACTION_CREATE_CONTINUE,
270 AuthManager::ACTION_LINK_CONTINUE,
281 case AuthManager::ACTION_LOGIN:
282 $action = AuthManager::ACTION_LOGIN_CONTINUE;
284 case AuthManager::ACTION_CREATE:
285 $action = AuthManager::ACTION_CREATE_CONTINUE;
287 case AuthManager::ACTION_LINK:
288 $action = AuthManager::ACTION_LINK_CONTINUE;
303 $authManager = AuthManager::singleton();
304 if ( !in_array( $action, static::$allowedActions,
true ) ) {
305 throw new InvalidArgumentException(
'invalid action: ' . $action );
310 : $authManager->getAuthenticationRequests( $action );
317 case AuthManager::ACTION_LOGIN:
318 case AuthManager::ACTION_LOGIN_CONTINUE:
319 return $authManager->canAuthenticateNow();
320 case AuthManager::ACTION_CREATE:
321 case AuthManager::ACTION_CREATE_CONTINUE:
322 return $authManager->canCreateAccounts();
323 case AuthManager::ACTION_LINK:
324 case AuthManager::ACTION_LINK_CONTINUE:
325 return $authManager->canLinkAccounts();
326 case AuthManager::ACTION_CHANGE:
327 case AuthManager::ACTION_REMOVE:
328 case AuthManager::ACTION_UNLINK:
332 throw new InvalidArgumentException(
'invalid action: ' . $action );
343 if ( !in_array( $action, static::$allowedActions,
true ) ) {
344 throw new InvalidArgumentException(
'invalid action: ' . $action );
347 $authManager = AuthManager::singleton();
352 case AuthManager::ACTION_LOGIN:
353 return $authManager->beginAuthentication(
$requests, $returnToUrl );
354 case AuthManager::ACTION_LOGIN_CONTINUE:
355 return $authManager->continueAuthentication(
$requests );
356 case AuthManager::ACTION_CREATE:
357 return $authManager->beginAccountCreation( $this->
getUser(), $requests,
359 case AuthManager::ACTION_CREATE_CONTINUE:
360 return $authManager->continueAccountCreation(
$requests );
361 case AuthManager::ACTION_LINK:
362 return $authManager->beginAccountLink( $this->
getUser(), $requests, $returnToUrl );
363 case AuthManager::ACTION_LINK_CONTINUE:
364 return $authManager->continueAccountLink(
$requests );
365 case AuthManager::ACTION_CHANGE:
366 case AuthManager::ACTION_REMOVE:
367 case AuthManager::ACTION_UNLINK:
369 throw new InvalidArgumentException(
'only one auth request can be changed at a time' );
371 throw new InvalidArgumentException(
'no auth request' );
374 $status = $authManager->allowsAuthenticationDataChange(
$req );
377 return AuthenticationResponse::newFail(
$status->getMessage() );
379 $authManager->changeAuthenticationData(
$req );
380 return AuthenticationResponse::newPass();
383 throw new InvalidArgumentException(
'invalid action: ' . $action );
400 $form = $this->
getAuthForm( $this->authRequests, $this->authAction );
401 $form->setSubmitCallback( [ $this,
'handleFormSubmit' ] );
407 if ( $sessionToken->wasNew() ) {
409 } elseif ( !$requestTokenValue ) {
411 } elseif ( !$sessionToken->match( $requestTokenValue ) ) {
415 $form->prepareForm();
422 throw new UnexpectedValueException(
'HTMLForm::trySubmit() returned true' );
423 } elseif (
$status ===
false ) {
431 } elseif ( is_string(
$status ) ) {
433 } elseif ( is_array(
$status ) ) {
434 if ( is_string( reset(
$status ) ) ) {
436 } elseif ( is_array( reset(
$status ) ) ) {
439 call_user_func_array( [
$status,
'fatal' ], $message );
442 throw new UnexpectedValueException(
'invalid HTMLForm::trySubmit() return value: '
443 .
'first element of array is ' . gettype( reset(
$status ) ) );
448 throw new UnexpectedValueException(
'invalid HTMLForm::trySubmit() return type: '
457 LoggerFactory::getInstance(
'authentication' )
458 ->warning(
'Validation error on return', [
'data' => $form->mFieldData,
459 'status' =>
$status->getWikiText() ] );
465 AuthManager::ACTION_CHANGE, AuthManager::ACTION_REMOVE, AuthManager::ACTION_UNLINK
467 if ( in_array( $this->authAction, $changeActions,
true ) &&
$status && !
$status->isOK() ) {
468 Hooks::run(
'ChangeAuthenticationDataAudit', [ reset( $this->authRequests ),
$status ] );
481 $requests = AuthenticationRequest::loadRequestsFromSubmission( $this->authRequests, $data );
513 $fieldInfo = AuthenticationRequest::mergeFieldInfo(
$requests );
518 return $formDescriptor;
537 $form->addHiddenField(
'authAction', $this->authAction );
551 $form = $this->
getAuthForm( $this->authRequests, $this->authAction );
552 $form->prepareForm()->displayForm(
$status );
566 $customSubmitButtonPresent =
false;
573 if (
$req->required === AuthenticationRequest::PRIMARY_REQUIRED ) {
575 $customSubmitButtonPresent =
true;
581 return !$customSubmitButtonPresent;
590 foreach (
$req->getFieldInfo()
as $field => $info ) {
591 if ( $info[
'type'] ===
'button' ) {
605 foreach ( $formDescriptor
as $field => &$definition ) {
607 if ( array_key_exists(
'class', $definition ) ) {
608 $class = $definition[
'class'];
609 } elseif ( array_key_exists(
'type', $definition ) ) {
612 if ( $class !==
'HTMLInfoField' ) {
613 $definition[
'tabindex'] = $i;
624 return $this->
getRequest()->getSession()->getToken(
'AuthManagerSpecialPage:'
633 return 'wpAuthToken';
646 $formDescriptor = [];
647 foreach ( $fieldInfo
as $fieldName => $singleFieldInfo ) {
655 LoggerFactory::getInstance(
'authentication' )->warning(
656 'AuthChangeFormFields hook changed auth requests' );
663 return $formDescriptor;
678 'name' => $fieldName,
681 if (
$type ===
'submit' && isset( $singleFieldInfo[
'label'] ) ) {
682 $descriptor[
'default'] = $singleFieldInfo[
'label']->plain();
683 } elseif (
$type !==
'submit' ) {
684 $descriptor += array_filter( [
686 'label-message' => self::getField( $singleFieldInfo,
'label' ),
689 if ( isset( $singleFieldInfo[
'options'] ) ) {
690 $descriptor[
'options'] = array_flip( array_map(
function ( $message ) {
692 return $message->parse();
693 }, $singleFieldInfo[
'options'] ) );
696 if ( isset( $singleFieldInfo[
'value'] ) ) {
697 $descriptor[
'default'] = $singleFieldInfo[
'value'];
700 if ( empty( $singleFieldInfo[
'optional'] ) ) {
701 $descriptor[
'required'] =
true;
717 foreach ( $formDescriptor
as &$field ) {
718 $field[
'__index'] = $i++;
720 uasort( $formDescriptor,
function ( $first, $second ) {
722 ?: $first[
'__index'] - $second[
'__index'];
724 foreach ( $formDescriptor
as &$field ) {
725 unset( $field[
'__index'] );
736 protected static function getField(
array $array, $fieldName, $default =
null ) {
737 if ( array_key_exists( $fieldName, $array ) ) {
738 return $array[$fieldName];
753 'password' =>
'password',
754 'select' =>
'select',
755 'checkbox' =>
'check',
756 'multiselect' =>
'multiselect',
757 'button' =>
'submit',
758 'hidden' =>
'hidden',
761 if ( !array_key_exists(
$type, $map ) ) {
762 throw new \LogicException(
'invalid field type: ' .
$type );