mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/OATHAuth
synced 2024-12-18 02:50:33 +00:00
Update for AuthManager
Handling enabling/disabling via AuthManager is left to a separate patch. Bug: T110457 Change-Id: Ic492b8f2477c475f8414b61505139e9a1df2ba5b
This commit is contained in:
parent
6f809fef27
commit
563796a98c
79
OATHAuth.hooks.legacy.php
Normal file
79
OATHAuth.hooks.legacy.php
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hooks for Extension:OATHAuth
|
||||||
|
* @deprecated B/C class for compatibility with pre-AuthManager core
|
||||||
|
*/
|
||||||
|
class OATHAuthLegacyHooks {
|
||||||
|
/**
|
||||||
|
* @param $extraFields array
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
static function ChangePasswordForm( &$extraFields ) {
|
||||||
|
$tokenField = array( 'wpOATHToken', 'oathauth-token', 'password', '' );
|
||||||
|
array_push( $extraFields, $tokenField );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $user User
|
||||||
|
* @param $password string
|
||||||
|
* @param $newpassword string
|
||||||
|
* @param &$errorMsg string
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
static function AbortChangePassword( $user, $password, $newpassword, &$errorMsg ) {
|
||||||
|
global $wgRequest;
|
||||||
|
|
||||||
|
$token = $wgRequest->getText( 'wpOATHToken' );
|
||||||
|
$oathrepo = OATHAuthHooks::getOATHUserRepository();
|
||||||
|
$oathuser = $oathrepo->findByUser( $user );
|
||||||
|
# Though it's weird to default to true, we only want to deny
|
||||||
|
# users who have two-factor enabled and have validated their
|
||||||
|
# token.
|
||||||
|
$result = true;
|
||||||
|
|
||||||
|
if ( $oathuser->getKey() !== null ) {
|
||||||
|
$result = $oathuser->getKey()->verifyToken( $token, $oathuser );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $result ) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
$errorMsg = 'oathauth-abortlogin';
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $user User
|
||||||
|
* @param $password string
|
||||||
|
* @param &$abort int
|
||||||
|
* @param &$errorMsg string
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
static function AbortLogin( $user, $password, &$abort, &$errorMsg ) {
|
||||||
|
$context = RequestContext::getMain();
|
||||||
|
$request = $context->getRequest();
|
||||||
|
$output = $context->getOutput();
|
||||||
|
|
||||||
|
$oathrepo = OATHAuthHooks::getOATHUserRepository();
|
||||||
|
$oathuser = $oathrepo->findByUser( $user );
|
||||||
|
$uid = CentralIdLookup::factory()->centralIdFromLocalUser( $user );
|
||||||
|
|
||||||
|
if ( $oathuser->getKey() !== null && !$request->getCheck( 'token' ) ) {
|
||||||
|
$encData = OATHAuthUtils::encryptSessionData(
|
||||||
|
$request->getValues(),
|
||||||
|
$uid
|
||||||
|
);
|
||||||
|
$request->setSessionData( 'oath_login', $encData );
|
||||||
|
$request->setSessionData( 'oath_uid', $uid );
|
||||||
|
$output->redirect( SpecialPage::getTitleFor( 'OATH' )->getFullURL( '', false, PROTO_CURRENT ) );
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use MediaWiki\Auth\AuthenticationRequest;
|
||||||
|
use MediaWiki\Auth\AuthManager;
|
||||||
|
use MediaWiki\Auth\ConfirmLinkSecondaryAuthenticationProvider;
|
||||||
|
use MediaWiki\Auth\EmailNotificationSecondaryAuthenticationProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hooks for Extension:OATHAuth
|
* Hooks for Extension:OATHAuth
|
||||||
*
|
*
|
||||||
|
@ -24,85 +29,63 @@ class OATHAuthHooks {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $extraFields array
|
* Register hooks which depend on MediaWiki core version
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
static function ChangePasswordForm( &$extraFields ) {
|
public static function onRegistration() {
|
||||||
$tokenField = array( 'wpOATHToken', 'oathauth-token', 'password', '' );
|
global $wgDisableAuthManager, $wgAuthManagerAutoConfig;
|
||||||
array_push( $extraFields, $tokenField );
|
|
||||||
|
|
||||||
return true;
|
if ( !$wgDisableAuthManager && class_exists( AuthManager::class ) ) {
|
||||||
}
|
$wgAuthManagerAutoConfig['secondaryauth'] += [
|
||||||
|
TOTPSecondaryAuthenticationProvider::class => [
|
||||||
/**
|
'class' => TOTPSecondaryAuthenticationProvider::class,
|
||||||
* @param $user User
|
// after non-interactive prroviders but before the ones that run after a
|
||||||
* @param $password string
|
// succesful authentication
|
||||||
* @param $newpassword string
|
'sort' => 50,
|
||||||
* @param &$errorMsg string
|
]
|
||||||
* @return bool
|
];
|
||||||
*/
|
Hooks::register( 'AuthChangeFormFields', 'OATHAuthHooks::onAuthChangeFormFields' );
|
||||||
static function AbortChangePassword( $user, $password, $newpassword, &$errorMsg ) {
|
|
||||||
global $wgRequest;
|
|
||||||
|
|
||||||
$token = $wgRequest->getText( 'wpOATHToken' );
|
|
||||||
$oathrepo = self::getOATHUserRepository();
|
|
||||||
$oathuser = $oathrepo->findByUser( $user );
|
|
||||||
# Though it's weird to default to true, we only want to deny
|
|
||||||
# users who have two-factor enabled and have validated their
|
|
||||||
# token.
|
|
||||||
$result = true;
|
|
||||||
|
|
||||||
if ( $oathuser->getKey() !== null ) {
|
|
||||||
$result = $oathuser->getKey()->verifyToken( $token, $oathuser );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $result ) {
|
|
||||||
return true;
|
|
||||||
} else {
|
} else {
|
||||||
$errorMsg = 'oathauth-abortlogin';
|
Hooks::register( 'AbortChangePassword', 'OATHAuthLegacyHooks::AbortChangePassword' );
|
||||||
|
Hooks::register( 'AbortLogin', 'OATHAuthLegacyHooks::AbortLogin' );
|
||||||
return false;
|
Hooks::register( 'ChangePasswordForm', 'OATHAuthLegacyHooks::ChangePasswordForm' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $user User
|
* @param AuthenticationRequest[] $requests
|
||||||
* @param $password string
|
* @param array $fieldInfo Field information array (union of the
|
||||||
* @param &$abort int
|
* AuthenticationRequest::getFieldInfo() responses).
|
||||||
* @param &$errorMsg string
|
* @param array $formDescriptor HTMLForm descriptor. The special key 'weight' can be set
|
||||||
|
* to change the order of the fields.
|
||||||
|
* @param string $action One of the AuthManager::ACTION_* constants.
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
static function AbortLogin( $user, $password, &$abort, &$errorMsg ) {
|
public static function onAuthChangeFormFields(
|
||||||
$context = RequestContext::getMain();
|
array $requests, array $fieldInfo, array &$formDescriptor, $action
|
||||||
$request = $context->getRequest();
|
) {
|
||||||
$output = $context->getOutput();
|
if ( isset( $fieldInfo['OATHToken'] ) ) {
|
||||||
|
$formDescriptor['OATHToken'] += [
|
||||||
$oathrepo = self::getOATHUserRepository();
|
'cssClass' => 'loginText',
|
||||||
$oathuser = $oathrepo->findByUser( $user );
|
'id' => 'wpOATHToken',
|
||||||
$uid = CentralIdLookup::factory()->centralIdFromLocalUser( $user );
|
'size' => 20,
|
||||||
|
'autofocus' => true,
|
||||||
if ( $oathuser->getKey() !== null && !$request->getCheck( 'token' ) ) {
|
'persistent' => false,
|
||||||
$encData = OATHAuthUtils::encryptSessionData(
|
];
|
||||||
$request->getValues(),
|
|
||||||
$uid
|
|
||||||
);
|
|
||||||
$request->setSessionData( 'oath_login', $encData );
|
|
||||||
$request->setSessionData( 'oath_uid', $uid );
|
|
||||||
$output->redirect( SpecialPage::getTitleFor( 'OATH' )->getFullURL( '', false, PROTO_CURRENT ) );
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if two-factor authentication is enabled for $wgUser
|
* Determine if two-factor authentication is enabled for $wgUser
|
||||||
*
|
*
|
||||||
* @param bool &$isEnabled Will be set to true if enabled, false otherwise
|
* This isn't the preferred mechanism for controlling access to sensitive features
|
||||||
|
* (see AuthManager::securitySensitiveOperationStatus() for that) but there is no harm in
|
||||||
|
* keeping it.
|
||||||
*
|
*
|
||||||
|
* @param bool &$isEnabled Will be set to true if enabled, false otherwise
|
||||||
* @return bool False if enabled, true otherwise
|
* @return bool False if enabled, true otherwise
|
||||||
*/
|
*/
|
||||||
static function TwoFactorIsEnabled( &$isEnabled ) {
|
public static function onTwoFactorIsEnabled( &$isEnabled ) {
|
||||||
global $wgUser;
|
global $wgUser;
|
||||||
|
|
||||||
$user = self::getOATHUserRepository()->findByUser( $wgUser );
|
$user = self::getOATHUserRepository()->findByUser( $wgUser );
|
||||||
|
@ -124,10 +107,9 @@ class OATHAuthHooks {
|
||||||
*
|
*
|
||||||
* @param User $user
|
* @param User $user
|
||||||
* @param array $preferences
|
* @param array $preferences
|
||||||
*
|
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public static function manageOATH( User $user, array &$preferences ) {
|
public static function onGetPreferences( User $user, array &$preferences ) {
|
||||||
if ( !$user->isAllowed( 'oathauth-enable' ) ) {
|
if ( !$user->isAllowed( 'oathauth-enable' ) ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -157,7 +139,7 @@ class OATHAuthHooks {
|
||||||
* @param DatabaseUpdater $updater
|
* @param DatabaseUpdater $updater
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public static function OATHAuthSchemaUpdates( $updater ) {
|
public static function onLoadExtensionSchemaUpdates( $updater ) {
|
||||||
$base = dirname( __FILE__ );
|
$base = dirname( __FILE__ );
|
||||||
switch ( $updater->getDB()->getType() ) {
|
switch ( $updater->getDB()->getType() ) {
|
||||||
case 'mysql':
|
case 'mysql':
|
||||||
|
@ -188,8 +170,7 @@ class OATHAuthHooks {
|
||||||
* Helper function for converting old users to the new schema
|
* Helper function for converting old users to the new schema
|
||||||
* @see OATHAuthHooks::OATHAuthSchemaUpdates
|
* @see OATHAuthHooks::OATHAuthSchemaUpdates
|
||||||
*
|
*
|
||||||
* @param DatabaseUpdater $updater
|
* @param DatabaseBase $db
|
||||||
*
|
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public static function schemaUpdateOldUsers( DatabaseBase $db ) {
|
public static function schemaUpdateOldUsers( DatabaseBase $db ) {
|
||||||
|
|
28
auth/TOTPAuthenticationRequest.php
Normal file
28
auth/TOTPAuthenticationRequest.php
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use MediaWiki\Auth\AuthenticationRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AuthManager value object for the TOTP second factor of an authentication: a pseudorandom token
|
||||||
|
* that is generated from the current time indepdendently by the server and the client.
|
||||||
|
*/
|
||||||
|
class TOTPAuthenticationRequest extends AuthenticationRequest {
|
||||||
|
public $OATHToken;
|
||||||
|
|
||||||
|
public function describeCredentials() {
|
||||||
|
return [
|
||||||
|
'provider' => wfMessage( 'oathauth-describe-provider' ),
|
||||||
|
'account' => new \RawMessage( '$1', [ $this->username ] ),
|
||||||
|
] + parent::describeCredentials();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFieldInfo() {
|
||||||
|
return array(
|
||||||
|
'OATHToken' => array(
|
||||||
|
'type' => 'string',
|
||||||
|
'label' => wfMessage( 'oathauth-auth-token-label' ),
|
||||||
|
'help' => wfMessage( 'oathauth-auth-token-help' ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
86
auth/TOTPSecondaryAuthenticationProvider.php
Normal file
86
auth/TOTPSecondaryAuthenticationProvider.php
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use MediaWiki\Auth\AbstractSecondaryAuthenticationProvider;
|
||||||
|
use MediaWiki\Auth\AuthenticationRequest;
|
||||||
|
use MediaWiki\Auth\AuthenticationResponse;
|
||||||
|
use MediaWiki\Auth\AuthManager;
|
||||||
|
use MediaWiki\Auth\Throttler;
|
||||||
|
use MediaWiki\Session\SessionManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AuthManager secondary authentication provider for TOTP second-factor authentication.
|
||||||
|
*
|
||||||
|
* After a successful primary authentication, requests a time-based one-time password
|
||||||
|
* (typically generated by a mobile app such as Google Authenticator) from the user.
|
||||||
|
*
|
||||||
|
* @see AuthManager
|
||||||
|
* @see https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm
|
||||||
|
*/
|
||||||
|
class TOTPSecondaryAuthenticationProvider extends AbstractSecondaryAuthenticationProvider {
|
||||||
|
|
||||||
|
public function getAuthenticationRequests( $action, array $options ) {
|
||||||
|
switch ( $action ) {
|
||||||
|
case AuthManager::ACTION_LOGIN:
|
||||||
|
// don't ask for anything initially so the second factor is on a separate screen
|
||||||
|
return [];
|
||||||
|
default:
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the user has enabled two-factor authentication, request a second factor.
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function beginSecondaryAuthentication( $user, array $reqs ) {
|
||||||
|
$oathuser = OATHAuthHooks::getOATHUserRepository()->findByUser( $user );
|
||||||
|
|
||||||
|
if ( $oathuser->getKey() === null ) {
|
||||||
|
return AuthenticationResponse::newAbstain();
|
||||||
|
} else {
|
||||||
|
return AuthenticationResponse::newUI( array( new TOTPAuthenticationRequest() ),
|
||||||
|
wfMessage( 'oathauth-auth-ui' ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the second factor.
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function continueSecondaryAuthentication( $user, array $reqs ) {
|
||||||
|
/** @var TOTPAuthenticationRequest $request */
|
||||||
|
$request = AuthenticationRequest::getRequestByClass( $reqs, TOTPAuthenticationRequest::class );
|
||||||
|
if ( !$request ) {
|
||||||
|
return AuthenticationResponse::newUI( array( new TOTPAuthenticationRequest() ),
|
||||||
|
wfMessage( 'oathauth-login-failed' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
$throttler = new Throttler( null, [ 'type' => 'TOTP' ] );
|
||||||
|
$result = $throttler->increase( $user->getName(), null, __METHOD__ );
|
||||||
|
if ( $result ) {
|
||||||
|
return AuthenticationResponse::newUI( array( new TOTPAuthenticationRequest() ),
|
||||||
|
new Message( 'oathauth-throttled', [ Message::durationParam( $result['wait'] ) ] ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
$oathuser = OATHAuthHooks::getOATHUserRepository()->findByUser( $user );
|
||||||
|
$token = $request->OATHToken;
|
||||||
|
|
||||||
|
if ( $oathuser->getKey() === null ) {
|
||||||
|
$this->logger->warning( 'Two-factor authentication was disabled mid-authentication for '
|
||||||
|
. $user->getName() );
|
||||||
|
return AuthenticationResponse::newAbstain();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $oathuser->getKey()->verifyToken( $token, $oathuser ) ) {
|
||||||
|
$throttler->clear( $user->getName(), null );
|
||||||
|
return AuthenticationResponse::newPass();
|
||||||
|
} else {
|
||||||
|
return AuthenticationResponse::newUI( array( new TOTPAuthenticationRequest() ),
|
||||||
|
wfMessage( 'oathauth-login-failed' ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function beginSecondaryAccountCreation( $user, $creator, array $reqs ) {
|
||||||
|
return AuthenticationResponse::newAbstain();
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@
|
||||||
"type": "other",
|
"type": "other",
|
||||||
"AutoloadClasses": {
|
"AutoloadClasses": {
|
||||||
"OATHAuthHooks": "OATHAuth.hooks.php",
|
"OATHAuthHooks": "OATHAuth.hooks.php",
|
||||||
|
"OATHAuthLegacyHooks": "OATHAuth.hooks.legacy.php",
|
||||||
"OATHAuthKey": "OATHAuthKey.php",
|
"OATHAuthKey": "OATHAuthKey.php",
|
||||||
"OATHAuthUtils": "OATHAuthUtils.php",
|
"OATHAuthUtils": "OATHAuthUtils.php",
|
||||||
"OATHUserRepository": "OATHUserRepository.php",
|
"OATHUserRepository": "OATHUserRepository.php",
|
||||||
|
@ -18,29 +19,23 @@
|
||||||
"SpecialOATHEnable": "special/SpecialOATHEnable.php",
|
"SpecialOATHEnable": "special/SpecialOATHEnable.php",
|
||||||
"SpecialOATHDisable": "special/SpecialOATHDisable.php",
|
"SpecialOATHDisable": "special/SpecialOATHDisable.php",
|
||||||
"SpecialOATHLogin": "special/SpecialOATHLogin.php",
|
"SpecialOATHLogin": "special/SpecialOATHLogin.php",
|
||||||
"ProxySpecialPage": "special/ProxySpecialPage.php"
|
"ProxySpecialPage": "special/ProxySpecialPage.php",
|
||||||
|
"TOTPAuthenticationRequest": "auth/TOTPAuthenticationRequest.php",
|
||||||
|
"TOTPSecondaryAuthenticationProvider": "auth/TOTPSecondaryAuthenticationProvider.php"
|
||||||
},
|
},
|
||||||
"ExtensionMessagesFiles": {
|
"ExtensionMessagesFiles": {
|
||||||
"OATHAuthAlias": "OATHAuth.alias.php"
|
"OATHAuthAlias": "OATHAuth.alias.php"
|
||||||
},
|
},
|
||||||
|
"callback": "OATHAuthHooks::onRegistration",
|
||||||
"Hooks": {
|
"Hooks": {
|
||||||
"AbortChangePassword": [
|
|
||||||
"OATHAuthHooks::AbortChangePassword"
|
|
||||||
],
|
|
||||||
"AbortLogin": [
|
|
||||||
"OATHAuthHooks::AbortLogin"
|
|
||||||
],
|
|
||||||
"ChangePasswordForm": [
|
|
||||||
"OATHAuthHooks::ChangePasswordForm"
|
|
||||||
],
|
|
||||||
"TwoFactorIsEnabled": [
|
"TwoFactorIsEnabled": [
|
||||||
"OATHAuthHooks::TwoFactorIsEnabled"
|
"OATHAuthHooks::onTwoFactorIsEnabled"
|
||||||
],
|
],
|
||||||
"LoadExtensionSchemaUpdates": [
|
"LoadExtensionSchemaUpdates": [
|
||||||
"OATHAuthHooks::OATHAuthSchemaUpdates"
|
"OATHAuthHooks::onLoadExtensionSchemaUpdates"
|
||||||
],
|
],
|
||||||
"GetPreferences": [
|
"GetPreferences": [
|
||||||
"OATHAuthHooks::manageOATH"
|
"OATHAuthHooks::onGetPreferences"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"MessagesDirs": {
|
"MessagesDirs": {
|
||||||
|
|
|
@ -45,5 +45,11 @@
|
||||||
"oathauth-step4": "Step 4: Verification",
|
"oathauth-step4": "Step 4: Verification",
|
||||||
"oathauth-entertoken": "Enter a code from your mobile app to verify:",
|
"oathauth-entertoken": "Enter a code from your mobile app to verify:",
|
||||||
"right-oathauth-enable": "Enable two-factor authentication",
|
"right-oathauth-enable": "Enable two-factor authentication",
|
||||||
"action-oathauth-enable": "enable two-factor authentication"
|
"action-oathauth-enable": "enable two-factor authentication",
|
||||||
|
"oathauth-auth-token-label": "Token",
|
||||||
|
"oathauth-auth-token-help": "The one-time password used as the second factor of two-factor authentication.",
|
||||||
|
"oathauth-auth-ui": "Please enter verification code from your mobile app",
|
||||||
|
"oathauth-throttled": "Too many verification attempts! Please wait $1.",
|
||||||
|
"oathauth-login-failed": "Verification failed.",
|
||||||
|
"oathauth-describe-provider": "Two-factor authentication (OATH)."
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,5 +49,11 @@
|
||||||
"oathauth-step4": "Label for step 4 information on Special:OATH",
|
"oathauth-step4": "Label for step 4 information on Special:OATH",
|
||||||
"oathauth-entertoken": "Label on input field on Special:OATH asking user to enter token",
|
"oathauth-entertoken": "Label on input field on Special:OATH asking user to enter token",
|
||||||
"right-oathauth-enable": "{{doc-right|oathauth-enable}}",
|
"right-oathauth-enable": "{{doc-right|oathauth-enable}}",
|
||||||
"action-oathauth-enable": "{{doc-action|oathauth-enable}}"
|
"action-oathauth-enable": "{{doc-action|oathauth-enable}}",
|
||||||
|
"oathauth-auth-token-label": "Label of the second-factor field on special pages and in the API",
|
||||||
|
"oathauth-auth-token-help": "Extended help message for the second factor field in the API.",
|
||||||
|
"oathauth-auth-ui": "Shown on top of the login form when second factor is required",
|
||||||
|
"oathauth-throttled": "Error message when throttling limit is hit.\n\nParameters:\n* $1 - throttle block duration",
|
||||||
|
"oathauth-login-failed": "Error message when verifying the second factor failed.",
|
||||||
|
"oathauth-describe-provider": "Description of the extension as an authentication provider."
|
||||||
}
|
}
|
||||||
|
|
17
tests/phpunit/TOTPAuthenticationRequestTest.php
Normal file
17
tests/phpunit/TOTPAuthenticationRequestTest.php
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use MediaWiki\Auth\AuthenticationRequestTestCase;
|
||||||
|
|
||||||
|
class TOTPAuthenticationRequestTest extends AuthenticationRequestTestCase {
|
||||||
|
|
||||||
|
protected function getInstance( array $args = [] ) {
|
||||||
|
return new TOTPAuthenticationRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideLoadFromSubmission() {
|
||||||
|
return [
|
||||||
|
[ [], [], false ],
|
||||||
|
[ [], [ 'OATHToken' => '123456' ], [ 'OATHToken' => '123456' ] ],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue