44 private $messageFormat;
54 $this->module = $module;
57 $this->messageFormat = $params[
'messageformat'] ??
'wikitext';
58 $this->authManager = $authManager ?: MediaWikiServices::getInstance()->getAuthManager();
68 return new self( $module, $authManager );
77 private function formatMessage( array &
$res, $key,
Message $message ) {
78 switch ( $this->messageFormat ) {
87 $res[$key] = $message->
setContext( $this->module )->parseAsBlock();
94 'key' => $message->
getKey(),
97 ApiResult::setIndexedTagName( $params,
'param' );
108 $status = $this->authManager->securitySensitiveOperationStatus( $operation );
110 case AuthManager::SEC_OK:
113 case AuthManager::SEC_REAUTH:
114 $this->module->dieWithError(
'apierror-reauthenticate' );
117 case AuthManager::SEC_FAIL:
118 $this->module->dieWithError(
'apierror-cannotreauthenticate' );
122 throw new UnexpectedValueException(
"Unknown status \"$status\"" );
134 $remove = array_fill_keys( $remove,
true );
135 $reqs = array_filter( $reqs,
static function ( $req ) use ( $remove ) {
136 return !isset( $remove[get_class( $req )] );
148 $params = $this->module->extractRequestParams();
150 $reqs = $this->authManager->getAuthenticationRequests( $action, $this->module->getUser() );
153 $wantedRequests =
null;
154 if ( isset( $params[
'requests'] ) ) {
155 $wantedRequests = array_fill_keys( $params[
'requests'],
true );
156 } elseif ( isset( $params[
'request'] ) ) {
157 $wantedRequests = [ $params[
'request'] =>
true ];
159 if ( $wantedRequests !==
null ) {
160 $reqs = array_filter(
163 return isset( $wantedRequests[$req->
getUniqueId()] );
171 foreach ( $reqs as $req ) {
172 $info = (array)$req->getFieldInfo();
174 $sensitive += array_filter( $info,
static function ( $opts ) {
175 return !empty( $opts[
'sensitive'] );
181 $data = array_intersect_key( $this->module->getRequest()->getValues(), $fields );
182 $this->module->getMain()->markParamsUsed( array_keys( $data ) );
185 $this->module->getMain()->markParamsSensitive( array_keys( $sensitive ) );
186 $this->module->requirePostedParameters( array_keys( $sensitive ),
'noprefix' );
189 return AuthenticationRequest::loadRequestsFromSubmission( $reqs, $data );
199 'status' =>
$res->status,
202 if (
$res->status === AuthenticationResponse::PASS &&
$res->username !==
null ) {
203 $ret[
'username'] =
$res->username;
206 if (
$res->status === AuthenticationResponse::REDIRECT ) {
207 $ret[
'redirecttarget'] =
$res->redirectTarget;
208 if (
$res->redirectApiData !==
null ) {
209 $ret[
'redirectdata'] =
$res->redirectApiData;
213 if (
$res->status === AuthenticationResponse::REDIRECT ||
214 $res->status === AuthenticationResponse::UI ||
215 $res->status === AuthenticationResponse::RESTART
220 if (
$res->status === AuthenticationResponse::FAIL ||
221 $res->status === AuthenticationResponse::UI ||
222 $res->status === AuthenticationResponse::RESTART
224 $this->formatMessage( $ret,
'message',
$res->message );
225 $ret[
'messagecode'] = ApiMessage::create(
$res->message )->getApiCode();
228 if (
$res->status === AuthenticationResponse::FAIL ||
229 $res->status === AuthenticationResponse::RESTART
231 $this->module->getRequest()->getSession()->set(
232 'ApiAuthManagerHelper::createRequest',
235 $ret[
'canpreservestate'] =
$res->createRequest !==
null;
237 $this->module->getRequest()->getSession()->remove(
'ApiAuthManagerHelper::createRequest' );
249 if ( !in_array( $result->status, [ AuthenticationResponse::PASS, AuthenticationResponse::FAIL ] ) ) {
254 LoggerFactory::getInstance(
'authevents' )->info(
"$module API attempt", [
256 'successful' => $result->status === AuthenticationResponse::PASS,
257 'status' => $result->message ? $result->message->getKey() :
'-',
267 $ret = $this->module->getRequest()->getSession()->get(
'ApiAuthManagerHelper::createRequest' );
278 $params = $this->module->extractRequestParams();
279 $mergeFields = !empty( $params[
'mergerequestfields'] );
281 $ret = [
'requests' => [] ];
282 foreach ( $reqs as $req ) {
283 $describe = $req->describeCredentials();
285 'id' => $req->getUniqueId(),
286 'metadata' => $req->getMetadata() + [ ApiResult::META_TYPE =>
'assoc' ],
288 switch ( $req->required ) {
289 case AuthenticationRequest::OPTIONAL:
290 $reqInfo[
'required'] =
'optional';
292 case AuthenticationRequest::REQUIRED:
293 $reqInfo[
'required'] =
'required';
295 case AuthenticationRequest::PRIMARY_REQUIRED:
296 $reqInfo[
'required'] =
'primary-required';
299 $this->formatMessage( $reqInfo,
'provider', $describe[
'provider'] );
300 $this->formatMessage( $reqInfo,
'account', $describe[
'account'] );
301 if ( !$mergeFields ) {
302 $reqInfo[
'fields'] = $this->formatFields( (array)$req->getFieldInfo() );
304 $ret[
'requests'][] = $reqInfo;
307 if ( $mergeFields ) {
308 $fields = AuthenticationRequest::mergeFieldInfo( $reqs );
309 $ret[
'fields'] = $this->formatFields( $fields );
322 private function formatFields( array $fields ) {
328 $module = $this->module;
331 foreach ( $fields as $name => $field ) {
332 $ret = array_intersect_key( $field, $copy );
334 if ( isset( $field[
'options'] ) ) {
335 $ret[
'options'] = array_map(
static function ( $msg ) use ( $module ) {
336 return $msg->setContext( $module )->plain();
337 }, $field[
'options'] );
340 $this->formatMessage( $ret,
'label', $field[
'label'] );
341 $this->formatMessage( $ret,
'help', $field[
'help'] );
342 $ret[
'optional'] = !empty( $field[
'optional'] );
343 $ret[
'sensitive'] = !empty( $field[
'sensitive'] );
345 $retFields[$name] = $ret;
362 ParamValidator::PARAM_TYPE =>
'string',
363 ParamValidator::PARAM_ISMULTI =>
true,
364 ApiBase::PARAM_HELP_MSG => [
'api-help-authmanagerhelper-requests', $action ],
367 ParamValidator::PARAM_TYPE =>
'string',
368 ParamValidator::PARAM_REQUIRED =>
true,
369 ApiBase::PARAM_HELP_MSG => [
'api-help-authmanagerhelper-request', $action ],
372 ParamValidator::PARAM_DEFAULT =>
'wikitext',
373 ParamValidator::PARAM_TYPE => [
'html',
'wikitext',
'raw',
'none' ],
374 ApiBase::PARAM_HELP_MSG =>
'api-help-authmanagerhelper-messageformat',
376 'mergerequestfields' => [
377 ParamValidator::PARAM_DEFAULT =>
false,
378 ApiBase::PARAM_HELP_MSG =>
'api-help-authmanagerhelper-mergerequestfields',
381 ParamValidator::PARAM_DEFAULT =>
false,
382 ApiBase::PARAM_HELP_MSG =>
'api-help-authmanagerhelper-preservestate',
385 ParamValidator::PARAM_TYPE =>
'string',
386 ApiBase::PARAM_HELP_MSG =>
'api-help-authmanagerhelper-returnurl',
389 ParamValidator::PARAM_DEFAULT =>
false,
390 ApiBase::PARAM_HELP_MSG =>
'api-help-authmanagerhelper-continue',
395 foreach ( $wantedParams as $name ) {
396 if ( isset( $params[$name] ) ) {
397 $ret[$name] = $params[$name];
Helper class for AuthManager-using API modules.
static newForModule(ApiBase $module, AuthManager $authManager=null)
Static version of the constructor, for chaining.
getPreservedRequest()
Fetch the preserved CreateFromLoginAuthenticationRequest, if any.
static getStandardParams( $action,... $wantedParams)
Fetch the standard parameters this helper recognizes.
static blacklistAuthenticationRequests(array $reqs, array $remove)
Filter out authentication requests by class name.
formatAuthenticationResponse(AuthenticationResponse $res)
Format an AuthenticationResponse for return.
__construct(ApiBase $module, AuthManager $authManager=null)
formatRequests(array $reqs)
Format an array of AuthenticationRequests for return.
securitySensitiveOperation( $operation)
Call $manager->securitySensitiveOperationStatus()
loadAuthenticationRequests( $action)
Fetch and load the AuthenticationRequests for an action.
logAuthenticationResult( $event, AuthenticationResponse $result)
Logs successful or failed authentication.
This abstract class implements many basic API functions, and is the base of all API classes.
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
getModuleName()
Get the name of the module being executed by this instance.
static setArrayType(array &$arr, $type, $kvpKeyName=null)
Set the array data type.
The Message class deals with fetching and processing of interface message into a variety of formats.
getParams()
Returns the message parameters.
getKey()
Returns the message key.
setContext(IContextSource $context)
Set the language and the title from a context object.
static stripOuterParagraph( $html)
Strip outer.