Skip to content

Login always fails for members with two-factor authentication enabled (Galette 1.3.0) #90

Closed

Description

@Linedwell

Versions

  • Galette 1.3.0 (official Docker image galette/galette:1.3.0)
  • plugin-oauth2 3.1.0

Description

Since Galette 1.3.0 introduced two-factor authentication, members who have a second factor enabled can no longer log in through the OAuth2 plugin.

The OAuth2 login form always shows "Check your login / email or password.", even though the credentials are correct.

Steps to reproduce

  1. On Galette 1.3.0, enable 2FA (optional mode is enough) and enrol a member account.
  2. From a client application (WordPress in our case), start the OAuth2 authorization flow.
  3. On the plugin login screen, enter the valid credentials of that member.

Expected: the member is asked for their second factor, then the authorization flow continues.
Actual: "Check your login / email or password." is shown, and the flow cannot go further.

Members without 2FA can still log in normally.

Logs

INFO  - User `xxxxx` logged in.
DEBUG - UserHelper::login(xxxxx) return ''
DEBUG - login() - URI: /plugins/oauth2/login

Galette accepts the password, but UserHelper::login() still returns false.

Analysis

UserHelper::login() calls Login::logIn() and then checks Login::isLogged().

Since Galette 1.3.0, Login::logIn() calls requireTwoFactor() when the member owes a second factor. isLogged() then stays false and isTwoFactorPending() becomes true until the code has been verified. As the comment in Login::needsTwoFactor() says, this fails closed on purpose for any caller outside the core that calls logIn() and then isLogged().

The plugin has no handling for the pending second factor (no TwoFactor reference anywhere), so it treats this state as a wrong password.

Possible fix

When logIn() succeeds and isTwoFactorPending() is true:

  • either redirect to Galette's core 2FA challenge, then come back to the OAuth2 authorization flow;
  • or show a second-factor step in the plugin login page.

As a minimum, showing a specific message such as "Two-factor authentication is not supported yet" would avoid sending users looking for a password error.

Activity

  1. added theissue type on Oct 13, 2026
  2. trasher commented on Oct 13, 2026

    @trasher
    Member

    May be fixed with #95, please test.

    Redirecting to core cannot work because plugin owes its own session- so it's been done on plugin side.

  3. Linedwell commented on Oct 13, 2026

    @Linedwell
    Author

    Will be tested when a tag will be published (my deployement script downloads a zip, it doesn't git clone the repository).

  4. trasher commented on Oct 13, 2026

    @trasher
    Member

    I'd need confirmation before merge; I do not want ot have to make another release to fix somehting that could have been found now.

  5. Linedwell commented on Oct 15, 2026

    @Linedwell
    Author

    I’ll test tonight. But I’ll have to bypass my upgrade pipeline as this isn’t a tagged release (that cannot be found by the script). I’ll provide my test and logs.

  6. Linedwell commented on Oct 15, 2026

    @Linedwell
    Author

    I can confirm that the fix works as intended:

    Here are the galette logs for my connection attempt.

    172.18.0.2 - 2026-10-15 16:51:25 - DEBUG - Trying to set locale to en_US
    172.18.0.2 - 2026-10-15 16:51:36 - DEBUG - Trying to set locale to fr_FR
    172.18.0.2 - 2026-10-15 16:51:36 - DEBUG - Redirect to /plugins/oauth2/login?redirect_url=%2Fplugins%2Foauth2%2Fauthorize%3Fstate%3D535faf3f1d04184c9b6f8252268cc10b%26response_type%3Dcode%26approval_prompt%3Dauto%26redirect_uri%3Dhttps%253A%252F%252Fblog.vikidia.org%252Fwp-login.php%253Fexternal%253Doauth2%26client_id%3Dgalette_wordpress
    172.18.0.2 - 2026-10-15 16:51:37 - DEBUG - login() - URI: /plugins/oauth2/login
    GET dump: Array
    (
        [redirect_url] => /plugins/oauth2/authorize?state=535faf3f1d04184c9b6f8252268cc10b&response_type=code&approval_prompt=auto&redirect_uri=https%3A%2F%2Fblog.vikidia.org%2Fwp-login.php%3Fexternal%3Doauth2&client_id=galette_wordpress
    ]
    
    
    172.18.0.2 - 2026-10-15 16:51:40 - INFO - User `Linedwell` logged in.
    172.18.0.2 - 2026-10-15 16:51:40 - DEBUG - Trying to set locale to fr_FR
    172.18.0.2 - 2026-10-15 16:51:40 - DEBUG - UserHelper::login(Linedwell) return ''
    172.18.0.2 - 2026-10-15 16:51:41 - DEBUG - twoFactor() - URI: /plugins/oauth2/two-factor
    172.18.0.2 - 2026-10-15 16:51:45 - DEBUG - UserHelper::verifySecondFactor() return '2'
    172.18.0.2 - 2026-10-15 16:51:45 - DEBUG - Scopes: member
    172.18.0.2 - 2026-10-15 16:51:45 - DEBUG - Old Temporary passwords have been deleted.
    172.18.0.2 - 2026-10-15 16:51:45 - INFO - Plugin "plugin-objectslend" is explicitly disabled
    172.18.0.2 - 2026-10-15 16:51:45 - DEBUG - authorization/authorize() - URI: /plugins/oauth2/authorize
    GET dump: Array
    (
        [response_type] => code
        [client_id] => galette_wordpress
        [redirect_uri] => https://blog.vikidia.org/wp-login.php?external=oauth2
        [state] => 535faf3f1d04184c9b6f8252268cc10b
    ]
    
    
    172.18.0.2 - 2026-10-15 16:51:45 - DEBUG - Scopes: member
    172.18.0.2 - 2026-10-15 16:51:46 - DEBUG - authorization/doAuthorize() - URI: /plugins/oauth2/authorize
    GET dump: Array
    (
        [response_type] => code
        [client_id] => galette_wordpress
        [redirect_uri] => https://blog.vikidia.org/wp-login.php?external=oauth2
        [state] => 535faf3f1d04184c9b6f8252268cc10b
    ]
    
    POST dump: Array
    (
        [approve] =>
    ]
    
    
    172.18.0.2 - 2026-10-15 16:51:46 - DEBUG - Scopes: member
    172.18.0.2 - 2026-10-15 16:51:46 - DEBUG - authorization/doAuthorize() exit ok
    172.18.0.2 - 2026-10-15 16:51:47 - DEBUG - Trying to set locale to en_US
    172.18.0.2 - 2026-10-15 16:51:47 - DEBUG - authorization/token() - URI: /plugins/oauth2/access_token
    POST dump: Array
    (
        [client_id] => galette_wordpress
        [client_secret] => HIDDEN
        [redirect_uri] => https://blog.vikidia.org/wp-login.php?external=oauth2
        [grant_type] => authorization_code
        [code] => HIDDEN
    ]
    
    
    172.18.0.2 - 2026-10-15 16:51:47 - DEBUG - authorization/token() exit ok
    172.18.0.2 - 2026-10-15 16:51:47 - DEBUG - Trying to set locale to en_US
    172.18.0.2 - 2026-10-15 16:51:47 - DEBUG - api/user() - URI: /plugins/oauth2/user
    
    172.18.0.2 - 2026-10-15 16:51:47 - DEBUG - api/user() load user #2
    172.18.0.2 - 2026-10-15 16:51:47 - DEBUG - Scopes: member
    172.18.0.2 - 2026-10-15 16:51:47 - DEBUG - Old Temporary passwords have been deleted.
    172.18.0.2 - 2026-10-15 16:51:47 - DEBUG - Trying to set locale to fr_FR
    172.18.0.2 - 2026-10-15 16:51:47 - DEBUG - Trying to set locale to en_US
    172.18.0.2 - 2026-10-15 16:51:47 - DEBUG - api/user() exit.
  7. trasher commented on Oct 15, 2026

    @trasher
    Member

    Great, thanks for testing! I'll make a new release soon with that fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions