*/
const TOKEN_LENGTH = 32;
+ /**
+ * @const string An invalid value for user_token
+ */
+ const INVALID_TOKEN = '*** INVALID ***';
+
/**
* Global constant made accessible as class constants so that autoloader
* magic can be used.
$user = self::newFromRow( $row );
// A user is considered to exist as a non-system user if it has a
- // password set, or a temporary password set, or an email set.
+ // password set, or a temporary password set, or an email set, or a
+ // non-invalid token.
$passwordFactory = new PasswordFactory();
$passwordFactory->init( RequestContext::getMain()->getConfig() );
try {
$newpassword = PasswordFactory::newInvalidPassword();
}
if ( !$password instanceof InvalidPassword || !$newpassword instanceof InvalidPassword
- || $user->mEmail
+ || $user->mEmail || $user->mToken !== self::INVALID_TOKEN
) {
// User exists. Steal it?
if ( !$options['steal'] ) {
__METHOD__
);
$user->invalidateEmail();
+ $user->mToken = self::INVALID_TOKEN;
$user->saveSettings();
+ SessionManager::singleton()->preventSessionsForUser( $user->getName() );
}
- SessionManager::singleton()->preventSessionsForUser( $user->getName() );
-
return $user;
}
$this->setToken();
}
- // If the user doesn't have a token, return null to indicate that.
- // Otherwise, hmac the version with the secret if we have a version.
if ( !$this->mToken ) {
+ // The user doesn't have a token, return null to indicate that.
return null;
+ } elseif ( $this->mToken === self::INVALID_TOKEN ) {
+ // We return a random value here so existing token checks are very
+ // likely to fail.
+ return MWCryptRand::generateHex( self::TOKEN_LENGTH );
} elseif ( $wgAuthenticationTokenVersion === null ) {
+ // $wgAuthenticationTokenVersion not in use, so return the raw secret
return $this->mToken;
} else {
+ // $wgAuthenticationTokenVersion in use, so hmac it.
$ret = MWCryptHash::hmac( $wgAuthenticationTokenVersion, $this->mToken, false );
// The raw hash can be overly long. Shorten it up.
*/
public function setToken( $token = false ) {
$this->load();
- if ( !$token ) {
+ if ( $this->mToken === self::INVALID_TOKEN ) {
+ \MediaWiki\Logger\LoggerFactory::getInstance( 'session' )
+ ->debug( __METHOD__ . ": Ignoring attempt to set token for system user \"$this\"" );
+ } elseif ( !$token ) {
$this->mToken = MWCryptRand::generateHex( self::TOKEN_LENGTH );
} else {
$this->mToken = $token;