* (T96041) __EXPECTUNUSEDCATEGORY__ on a category page causes the category
to be hidden on Special:UnusedCategories.
* Add PasswordPolicy to check the password isn't in the large blacklist.
+* The AuthManagerLoginAuthenticateAudit hook has a new parameter for
+ additional information about the authentication event.
* …
=== External library changes in 1.33 ===
$user: The User object being authenticated against, or null if authentication
failed before getting that far.
$username: A guess at the user name being authenticated, or null if we can't
- even determine that.
+ even determine that. When $user is not null, it can be in the form of
+ <username>@<more info> (e.g. for bot passwords).
+$extraData: An array (string => string) with extra information, intended to be
+ added to log contexts. Fields it might include:
+ - appId: the application ID, only if the login was with a bot password
'AuthPluginAutoCreate': DEPRECATED since 1.27! Use the 'LocalUserCreated' hook
instead. Called when creating a local account for an user logged in from an
$this->setSessionDataForUser( $user );
$this->callMethodOnProviders( 7, 'postAuthentication', [ $user, $ret ] );
$session->remove( 'AuthManager::authnState' );
- \Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $ret, $user, $user->getName() ] );
+ \Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $ret, $user, $user->getName(), [] ] );
return $ret;
}
$this->callMethodOnProviders( 7, 'postAuthentication',
[ User::newFromName( $guessUserName ) ?: null, $ret ]
);
- \Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $ret, null, $guessUserName ] );
+ \Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $ret, null, $guessUserName, [] ] );
return $ret;
}
}
[ User::newFromName( $guessUserName ) ?: null, $res ]
);
$session->remove( 'AuthManager::authnState' );
- \Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $res, null, $guessUserName ] );
+ \Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $res, null, $guessUserName, [] ] );
return $res;
case AuthenticationResponse::ABSTAIN;
// Continue loop
[ User::newFromName( $guessUserName ) ?: null, $res ]
);
$session->remove( 'AuthManager::authnState' );
- \Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $res, null, $guessUserName ] );
+ \Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $res, null, $guessUserName, [] ] );
return $res;
case AuthenticationResponse::REDIRECT;
case AuthenticationResponse::UI;
);
$this->callMethodOnProviders( 7, 'postAuthentication', [ $user, $ret ] );
$session->remove( 'AuthManager::authnState' );
- \Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $ret, $user, $user->getName() ] );
+ \Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $ret, $user, $user->getName(), [] ] );
return $ret;
}
}
$this->logger->debug( "Login failed in secondary authentication by $id" );
$this->callMethodOnProviders( 7, 'postAuthentication', [ $user, $res ] );
$session->remove( 'AuthManager::authnState' );
- \Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $res, $user, $user->getName() ] );
+ \Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $res, $user, $user->getName(), [] ] );
return $res;
case AuthenticationResponse::REDIRECT;
case AuthenticationResponse::UI;
$this->callMethodOnProviders( 7, 'postAuthentication', [ $user, $ret ] );
$session->remove( 'AuthManager::authnState' );
$this->removeAuthenticationSessionData( null );
- \Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $ret, $user, $user->getName() ] );
+ \Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $ret, $user, $user->getName(), [] ] );
return $ret;
} catch ( \Exception $ex ) {
$session->remove( 'AuthManager::authnState' );
// Split name into name+appId
$sep = self::getSeparator();
if ( strpos( $username, $sep ) === false ) {
- return self::loginHook( $username, Status::newFatal( 'botpasswords-invalid-name', $sep ) );
+ return self::loginHook( $username, null, Status::newFatal( 'botpasswords-invalid-name', $sep ) );
}
list( $name, $appId ) = explode( $sep, $username, 2 );
// Find the named user
$user = User::newFromName( $name );
if ( !$user || $user->isAnon() ) {
- return self::loginHook( $user ?: $name, Status::newFatal( 'nosuchuser', $name ) );
+ return self::loginHook( $user ?: $name, null, Status::newFatal( 'nosuchuser', $name ) );
}
if ( $user->isLocked() ) {
$result = $throttle->increase( $user->getName(), $request->getIP(), __METHOD__ );
if ( $result ) {
$msg = wfMessage( 'login-throttled' )->durationParams( $result['wait'] );
- return self::loginHook( $user, Status::newFatal( $msg ) );
+ return self::loginHook( $user, null, Status::newFatal( $msg ) );
}
}
// Get the bot password
$bp = self::newFromUser( $user, $appId );
if ( !$bp ) {
- return self::loginHook( $user, Status::newFatal( 'botpasswords-not-exist', $name, $appId ) );
+ return self::loginHook( $user, $bp,
+ Status::newFatal( 'botpasswords-not-exist', $name, $appId ) );
}
// Check restrictions
$status = $bp->getRestrictions()->check( $request );
if ( !$status->isOK() ) {
- return self::loginHook( $user, Status::newFatal( 'botpasswords-restriction-failed' ) );
+ return self::loginHook( $user, $bp, Status::newFatal( 'botpasswords-restriction-failed' ) );
}
// Check the password
$passwordObj = $bp->getPassword();
if ( $passwordObj instanceof InvalidPassword ) {
- return self::loginHook( $user, Status::newFatal( 'botpasswords-needs-reset', $name, $appId ) );
+ return self::loginHook( $user, $bp,
+ Status::newFatal( 'botpasswords-needs-reset', $name, $appId ) );
}
if ( !$passwordObj->equals( $password ) ) {
- return self::loginHook( $user, Status::newFatal( 'wrongpassword' ) );
+ return self::loginHook( $user, $bp, Status::newFatal( 'wrongpassword' ) );
}
// Ok! Create the session.
if ( $throttle ) {
$throttle->clear( $user->getName(), $request->getIP() );
}
- return self::loginHook(
- $user,
- Status::newGood( $provider->newSessionForRequest( $user, $bp, $request ) )
- );
+ return self::loginHook( $user, $bp,
+ Status::newGood( $provider->newSessionForRequest( $user, $bp, $request ) ) );
}
/**
* AuthManager, call the AuthManagerLoginAuthenticateAudit hook.
*
* @param User|string $user User being logged in
+ * @param BotPassword|null $bp Bot sub-account, if it can be identified
* @param Status $status Login status
* @return Status The passed-in status
*/
- private static function loginHook( $user, Status $status ) {
+ private static function loginHook( $user, $bp, Status $status ) {
+ $extraData = [];
if ( $user instanceof User ) {
$name = $user->getName();
+ if ( $bp ) {
+ $extraData['appId'] = $name . self::getSeparator() . $bp->getAppId();
+ }
} else {
$name = $user;
$user = null;
} else {
$response = AuthenticationResponse::newFail( $status->getMessage() );
}
- Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $response, $user, $name ] );
+ Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $response, $user, $name, $extraData ] );
return $status;
}