Failed login can still redirect to the "Post login path"

Created on 10 September 2024, 3 months ago

Problem/Motivation

If registrations are disabled on a site, but a user that exists in the identity portal tries to log in, the module will try to create the user, fail silently (messages will be added in watchdog and messenger) and try to redirect to the afterLogin route.

It will also trigger a LogginEvent, which is wrong as well.

If this route happens to be /user, you will end up in an infinite loop, as it will try to log the user in again. If it's not, then the user will see the error messages in a 403 page, if the "Post login path" route was restricted. If the page is public, then they will just see the error messages.

So, 2 out of 3 outcomes are not desired here.

Watchdog messages are:
- Failed to create user. User registration is disabled. Name: john-doe, email: john-doe@test.com
- Login for user john-doe prevented. Account is blocked. <=== this is wrong, it's just because it is the anonymous user, which is not active.

Proposed resolution

I suggest:
- Checking that registrations are disabled before trying to create a user, and redirect to the front page in that case.
- Checking that the user is authenticated before triggering the LoggingEvent

Remaining tasks

MR. I have the code already, I'm creating it.

πŸ› Bug report
Status

Active

Version

4.1

Component

Code

Created by

πŸ‡ͺπŸ‡ΈSpain fjgarlin

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @fjgarlin
  • Merge request !31Check if authentication was as expected. β†’ (Merged) created by fjgarlin
  • Status changed to Needs review 3 months ago
  • πŸ‡ͺπŸ‡ΈSpain fjgarlin

    The changes are ready for review.

  • Pipeline finished with Success
    3 months ago
    Total: 235s
    #279222
  • Status changed to Needs work 3 months ago
  • πŸ‡ΊπŸ‡ΈUnited States wells Seattle, WA

    Yes, we should include a test for this one.

  • πŸ‡ͺπŸ‡ΈSpain fjgarlin

    I'm not sure I'd know how to begin. We'd need to mock remote data, set an integration and settings in it (like disallow registrations) and then test the workflow. I don't see any test doing something similar yet.

    For context, I found this bug integrating the new D10 version of www.drupal.org with the new keycloak system. We want registrations to always go via D7, therefore not allowing registrations on D10.

    When working with existing users, everything works well, but when the user does not exist yet in D10, then we get the above watchdog messages and behaviour.

    If I get some boiler plate code for the above from any of you that know the module better I could finish it off.

  • Status changed to Needs review 3 months ago
  • πŸ‡ΊπŸ‡ΈUnited States wells Seattle, WA

    Ack. Good point. This would be difficult to test. Happy merge it someone else is able to do some functional review and get it to RTBC. Otherwise, I'll try to do so eventually. Thanks, @fjgarlin.

  • Pipeline finished with Canceled
    2 months ago
    Total: 200s
    #306232
  • Pipeline finished with Success
    2 months ago
    Total: 209s
    #306235
  • πŸ‡ͺπŸ‡ΈSpain fjgarlin

    I actually found another case of infinite loop to "user.login" or a nasty error which is not captured.

    The website encountered an unexpected error. Try again later.
    
    TypeError: Stevenmaguire\OAuth2\Client\Provider\Keycloak::getResourceOwner(): Argument #1 ($token) must be of type League\OAuth2\Client\Token\AccessToken, null given, called in /app/web/modules/contrib/social_auth_keycloak/src/KeycloakAuthManager.php on line 62 in Stevenmaguire\OAuth2\Client\Provider\Keycloak->getResourceOwner() (line 269 of /app/vendor/stevenmaguire/oauth2-keycloak/src/Provider/Keycloak.php).
    Drupal\social_auth_keycloak\KeycloakAuthManager->getUserInfo() (Line: 308)
    Drupal\social_auth\Controller\OAuth2ControllerBase->processCallback() (Line: 197)
    Drupal\social_auth\Controller\OAuth2ControllerBase->callback()
    call_user_func_array() (Line: 123)
    

    If the credentials are wrong, we don't get a token back, so I'm checking for that before going any further. I discovered that the "processCallback" function does not handle any possible error, so I added a differentiation and multiple error codes that can help when debugging.

    So, the current MR avoid two cases of infinite redirects to "user.login" and a case for an exception being thrown, and instead it captures the errors and redirects to the homepage instead.

  • Pipeline finished with Success
    2 months ago
    Total: 159s
    #306246
  • πŸ‡ΊπŸ‡ΈUnited States wells Seattle, WA

    Thanks for your work on this, @fjgarlin -- I left a question on the MR that I think will ultimately lead to some additional changes needed. Let me know your thoughts.

  • πŸ‡ͺπŸ‡ΈSpain fjgarlin

    Maybe you couldn’t see the whole MR code? The changes you were asking about were addressed already and shown in the MR.

  • Pipeline finished with Success
    2 months ago
    Total: 156s
    #307055
  • πŸ‡ͺπŸ‡ΈSpain fjgarlin

    I refactored the solution as per the feedback in the MR. It can be reviewed again. The approach is the same, it's about catching the error in the "processCallback" function, and then being able to act on it in the "callback" method to avoid an infinite login loop.

  • Pipeline finished with Skipped
    about 1 month ago
    #331216
  • πŸ‡ΊπŸ‡ΈUnited States wells Seattle, WA

    Looks good to go -- thanks!

  • Status changed to Fixed 28 days ago
  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024