Одноразовые пароли с mediawiki AuthPlugin

Я создал расширение AuthPlugin для аутентификации по одноразовому паролю SecurID. Все идет нормально. Я могу аутентифицировать и создавать пользователей при первом входе в систему. Однако первый вход всегда проходит аутентификацию дважды. Он аутентифицируется в первый раз, чтобы создать пользователя, и во второй раз, чтобы фактически войти в систему. Здесь вы можете увидеть проблему: одноразовый пароль используется в первый раз, поэтому пользователь не вошел в систему. Последующие входы в систему работают нормально. .

Я проследил первые вызовы авторизации на /includes/specials/SpecialUserlogin.php (и я не уверен, какой из них вызывается, но я мог найти оскорбительный и удалить его):

<?php
/**
 * Make a new user account using the loaded data.
 * @private
 * @throws PermissionsError|ReadOnlyError
 * @return Status
 */
public function addNewAccountInternal() {
    // ...snip...
    // If we are not allowing users to login locally, we should be checking
    // to see if the user is actually able to authenticate to the authenti-
    // cation server before they create an account (otherwise, they can
    // create a local account and login as any domain user). We only need
    // to check this for domains that aren't local.
    if ( 'local' != $this->mDomain && $this->mDomain != '' ) {
        if (
            !$wgAuth->canCreateAccounts() &&
            (
                !$wgAuth->userExists( $this->mUsername ) ||
                !$wgAuth->authenticate( $this->mUsername, $this->mPassword )
            )
        ) {
            return Status::newFatal( 'wrongpassword' );
        }
    }

//...snip...
/**
 * Attempt to automatically create a user on login. Only succeeds if there
 * is an external authentication method which allows it.
 *
 * @param $user User
 *
 * @return integer Status code
 */
function attemptAutoCreate( $user ) {
   // ...snip...
    if ( !$wgAuth->authenticate( $user->getName(), $this->mPassword ) ) {
        wfDebug( __METHOD__ . ": \$wgAuth->authenticate() returned false, aborting\n" );

        return self::WRONG_PLUGIN_PASS;
    }

Итак, если всем пользователям необходимо аутентифицироваться с помощью системы одноразовых паролей (если я запрещаю вход в систему с локальных учетных записей и создание локальных учетных записей), есть ли проблема с удалением оскорбительных вызовов authenticate? Я ужасно неуверенна здесь? Или есть лучший способ сделать это? Должен ли я делать что-то кроме расширения AuthPlugin? Например, я переопределяю эти методы AuthPlugin:

<?php
/**
 * Return true to prevent logins that don't authenticate here from being
 * checked against the local database's password fields.
 *
 * This is just a question, and shouldn't perform any actions.
 *
 * @return bool
 */
public function strict() {
    return true;
}

/**
 * Check if a user should authenticate locally if the global authentication fails.
 * If either this or strict() returns true, local authentication is not used.
 *
 * @param string $username Username.
 * @return bool
 */
public function strictUserAuth( $username ) {
    return true;
}

Я хотел бы избежать предварительного создания всех пользователей и их синхронизации, но это был бы один из способов избежать первоначальных дублирующих вызовов аутентификации.

Кстати, я думаю, что настоящий вызов аутентификации для сеанса происходит в includes/User.php:

<?php
public function checkPassword( $password ) {
    global $wgAuth, $wgLegacyEncoding;
    $this->load();

    // Certain authentication plugins do NOT want to save
    // domain passwords in a mysql database, so we should
    // check this (in case $wgAuth->strict() is false).

    if ( $wgAuth->authenticate( $this->getName(), $password ) ) {
        return true;

person zerodiff    schedule 23.10.2014    source источник


Ответы (1)


Я думаю, что лучше всего использовать тот же способ, что и расширение TwoFactorAuthentication, используемое в wikitech. wikimedia.org.

Вы можете использовать AbortLogin хук, чтобы проверить свой одноразовый пароль до того, как данные пользователя проверено. Проблема: Вы должны убедиться, что одноразовый пароль помечен как «использованный» только тогда, когда пользователь успешно вошел в систему.

(Надеюсь, вы не захотите заменить «обычный» пароль пользователя «только» одноразовым паролем).

person Florian    schedule 27.10.2014
comment
Мне нравится ваш ответ, но на самом деле это не двухфакторный... это всего лишь один одноразовый пароль без статического пароля. Таким образом, нет статического пароля для аутентификации (если я что-то здесь не упустил). - person zerodiff; 28.10.2014
comment
Argh, я думаю, что немного неправильно понял ваш вопрос :) Чтобы избежать первого вызова аутентификации, должно быть достаточно реализовать getDomain() в вашем AuthPlugin и возвращать только 'local'. - person Florian; 28.10.2014
comment
Спасибо - я проверю это и посмотрю, что я узнаю. - person zerodiff; 29.10.2014