2015-11-22 20:17:00 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace MediaWiki\Auth;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @group AuthManager
|
2018-11-01 11:48:52 +00:00
|
|
|
* @covers \MediaWiki\Auth\AuthenticationResponse
|
2015-11-22 20:17:00 +00:00
|
|
|
*/
|
2019-06-30 13:23:53 +00:00
|
|
|
class AuthenticationResponseTest extends \MediaWikiUnitTestCase {
|
2015-11-22 20:17:00 +00:00
|
|
|
/**
|
|
|
|
|
* @dataProvider provideConstructors
|
|
|
|
|
* @param string $constructor
|
|
|
|
|
* @param array $args
|
2022-05-28 06:56:01 +00:00
|
|
|
* @param array|\Exception $expect
|
2015-11-22 20:17:00 +00:00
|
|
|
*/
|
|
|
|
|
public function testConstructors( $constructor, $args, $expect ) {
|
|
|
|
|
if ( is_array( $expect ) ) {
|
|
|
|
|
$res = new AuthenticationResponse();
|
2016-07-01 16:26:20 +00:00
|
|
|
$res->messageType = 'warning';
|
2015-11-22 20:17:00 +00:00
|
|
|
foreach ( $expect as $field => $value ) {
|
|
|
|
|
$res->$field = $value;
|
|
|
|
|
}
|
2020-05-29 06:46:30 +00:00
|
|
|
$ret = AuthenticationResponse::$constructor( ...$args );
|
2015-11-22 20:17:00 +00:00
|
|
|
$this->assertEquals( $res, $ret );
|
|
|
|
|
} else {
|
|
|
|
|
try {
|
2020-05-29 06:46:30 +00:00
|
|
|
AuthenticationResponse::$constructor( ...$args );
|
2015-11-22 20:17:00 +00:00
|
|
|
$this->fail( 'Expected exception not thrown' );
|
|
|
|
|
} catch ( \Exception $ex ) {
|
|
|
|
|
$this->assertEquals( $expect, $ex );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function provideConstructors() {
|
|
|
|
|
$req = $this->getMockForAbstractClass( AuthenticationRequest::class );
|
|
|
|
|
$msg = new \Message( 'mainpage' );
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
[ 'newPass', [], [
|
|
|
|
|
'status' => AuthenticationResponse::PASS,
|
|
|
|
|
] ],
|
|
|
|
|
[ 'newPass', [ 'name' ], [
|
|
|
|
|
'status' => AuthenticationResponse::PASS,
|
|
|
|
|
'username' => 'name',
|
|
|
|
|
] ],
|
|
|
|
|
[ 'newPass', [ 'name', null ], [
|
|
|
|
|
'status' => AuthenticationResponse::PASS,
|
|
|
|
|
'username' => 'name',
|
|
|
|
|
] ],
|
|
|
|
|
|
|
|
|
|
[ 'newFail', [ $msg ], [
|
|
|
|
|
'status' => AuthenticationResponse::FAIL,
|
|
|
|
|
'message' => $msg,
|
2016-07-01 16:26:20 +00:00
|
|
|
'messageType' => 'error',
|
Allow AuthenticationResponse to store private failure reasons
Allows AuthenticationResponse to store, when the status is FAIL,
an array of strings that describe the reasons for the failure.
These are stored in $failReasons and are not intended for the
client. On any other status $failReasons is null. These are
optionally provided when calling AuthenticationResponse::newFail
in the parameter $failReasons.
This is implemented to allow the CentralAuth extension to store
whether the password was correct if the account is locked inside
the AuthenticationResponse. The extension CheckUser which hooks
into authentication requests then can read the failure reasons
from the AuthenticationResponse, and can then note in the CU
entry that the login attempt had the correct password.
If whether the correct password was used is stored in the I18n
message, the client would then know if the password they tried
on the locked account was correct. For comprimised accounts this
could be used by mailicious actors to verify that the password
was correct and then try it elsewhere if the account has the same
password as on other sites. This means, unless I have missed
another method, a new array is needed to store these failure reasons.
This, along with some other patches to CheckUser and CentralAuth,
will then allow Checkusers to see if a login attempt for a locked
account had the correct password. Checkusers can then use this,
with the knowledge that the account isn't comprimised, to say that
the login attempt was made by the owner of the account so in cases
of socking the creation of a new account can be more conclusively
said to be by the person who created the now locked sock account.
Bug: T303192
Change-Id: I7b2d9579a518a6c02f05281b1016e31e0d086fe7
2022-05-14 14:09:04 +00:00
|
|
|
'failReasons' => []
|
2015-11-22 20:17:00 +00:00
|
|
|
] ],
|
|
|
|
|
|
|
|
|
|
[ 'newRestart', [ $msg ], [
|
|
|
|
|
'status' => AuthenticationResponse::RESTART,
|
|
|
|
|
'message' => $msg,
|
|
|
|
|
] ],
|
|
|
|
|
|
|
|
|
|
[ 'newAbstain', [], [
|
|
|
|
|
'status' => AuthenticationResponse::ABSTAIN,
|
|
|
|
|
] ],
|
|
|
|
|
|
|
|
|
|
[ 'newUI', [ [ $req ], $msg ], [
|
|
|
|
|
'status' => AuthenticationResponse::UI,
|
|
|
|
|
'neededRequests' => [ $req ],
|
|
|
|
|
'message' => $msg,
|
2016-07-01 16:26:20 +00:00
|
|
|
'messageType' => 'warning',
|
|
|
|
|
] ],
|
|
|
|
|
|
|
|
|
|
[ 'newUI', [ [ $req ], $msg, 'warning' ], [
|
|
|
|
|
'status' => AuthenticationResponse::UI,
|
|
|
|
|
'neededRequests' => [ $req ],
|
|
|
|
|
'message' => $msg,
|
|
|
|
|
'messageType' => 'warning',
|
|
|
|
|
] ],
|
|
|
|
|
|
|
|
|
|
[ 'newUI', [ [ $req ], $msg, 'error' ], [
|
|
|
|
|
'status' => AuthenticationResponse::UI,
|
|
|
|
|
'neededRequests' => [ $req ],
|
|
|
|
|
'message' => $msg,
|
|
|
|
|
'messageType' => 'error',
|
2015-11-22 20:17:00 +00:00
|
|
|
] ],
|
|
|
|
|
[ 'newUI', [ [], $msg ],
|
|
|
|
|
new \InvalidArgumentException( '$reqs may not be empty' )
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
[ 'newRedirect', [ [ $req ], 'http://example.org/redir' ], [
|
|
|
|
|
'status' => AuthenticationResponse::REDIRECT,
|
|
|
|
|
'neededRequests' => [ $req ],
|
|
|
|
|
'redirectTarget' => 'http://example.org/redir',
|
|
|
|
|
] ],
|
|
|
|
|
[
|
|
|
|
|
'newRedirect',
|
|
|
|
|
[ [ $req ], 'http://example.org/redir', [ 'foo' => 'bar' ] ],
|
|
|
|
|
[
|
|
|
|
|
'status' => AuthenticationResponse::REDIRECT,
|
|
|
|
|
'neededRequests' => [ $req ],
|
|
|
|
|
'redirectTarget' => 'http://example.org/redir',
|
|
|
|
|
'redirectApiData' => [ 'foo' => 'bar' ],
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
[ 'newRedirect', [ [], 'http://example.org/redir' ],
|
|
|
|
|
new \InvalidArgumentException( '$reqs may not be empty' )
|
|
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|