PLATFORM
  • Tails

    Create websites with TailwindCSS

  • Blocks

    Design blocks for your website

  • Wave

    Start building the next great SAAS

  • Pines

    Alpine & Tailwind UI Library

  • Auth

    Plug'n Play Authentication for Laravel

  • Designer comingsoon

    Create website designs with AI

  • DevBlog comingsoon

    Blog platform for developers

  • Static

    Build a simple static website

  • SaaS Adventure

    21-day program to build a SAAS

Question By
Unsolved

Login Bug | Laravel/Wave

patrickkoehli93

Sep 6th, 2023 12:19 AM

Does anyone else also experience a login error when they log out of their Laravel/Wave website on Chrome an Android mobile phone and try to log back in with another account?

Especially if auto-fill is used for the credentials, the login attempt goes wrong. It seems to be a CSRF token error. I could already find out that sometimes 3 token checks are made for a login attempt. While two of them are successful, the third attempt checks the old token for reasons I can't yet explain - and of course this check goes wrong and you end up on a white page or receive the error message "expired".

The error has actually been occurring since the beginning, mostly, as I said, with Android devices. However, it has also rarely occurred on iOS devices on Safari. As we have more and more users who can have multiple accounts, fixing this problem has become more important again.

I'm curious to know if anyone knows about this problem and, at best, has a solution for it.

bobbyiliev

Sep 6th, 2023 01:11 PM

Hi there,

Is your Wave app deployed on the DigitalOcean App Platform? If so, the problem that you've described might occur when you have configured your app to run on multiple containers. this causes an issue with the login session.

To fix that, you could use a redis cluster to store your sessions in.

If this is not the case, can you share the exact error that you are seeing when you try to login? And also is it a plain Wave app or have you made any changes to the auth logic?

patrickkoehli93

Sep 7th, 2023 11:38 PM

Hi Bobby Thank you for your answer. No, the app runs on a Linux-Server from a random hoster, so we're not running to the app on multiple containers. Also we have not made any changes to the auth logic. Unfortunately there's no log-entry for the failed csrf-token verification, so that's why I tried to better understand the misbehaviour yesterday. Here's what I noticed:

  • The error only seems to be there when the auto-fill method is used on Android devices (no matter what OS version).
  • When user1 logs out, the old session is invalidated and the token is regenerated. This new token is then also used to log in user2. On successful attempts, the request token is checked to see if it matches the session token (\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\VerifyCsrfToken.php - function tokensMatch() ).
  • When using Auto-Fill in the Chrome browser on Android, the tokensMatch function is sometimes called twice (in some cases even three times). The first call is successful and the freshly generated token from the previous logout is checked in the session and request. For reasons that are still inexplicable to me, however, a second (or even third) call of the function tokensMatch is sometimes made, in which the request token is still the "old"/identical token as in the previous attempt, but the session token has changed in the meantime and of course no longer matches, so that the check fails. In this case, the user sees a 419 page expired error. The new Session Token is completely new. I initially thought that it might be the old session token from the previous session, but that is not the case.
  • In this case, if the user simply overwrites the link manually and wants to go to the start page, for example, then he is actually logged in. The redirect from the login procedure simply does not work because the token validation fails.
  • I could not find this behaviour on iOS devices, but there I noticed a difference between Android Auto-Fill and iOS Auto-Fill: On Android, not only are the credentials put into the login fields, but the data is also sent automatically. With iOS, only the fields are filled in. On iOS devices, the user has to submit the form manually by clicking on the designated login button. It seems that a new session token is generated when trying to log in with Auto-Fill and automatically submitting the form at a certain point in time. Unfortunately, the error does not always occur. Yesterday I was able to log out with User1 and log in again with User2 and Auto-Fill over 20 times without an error occurring. If it occurred once, then every further login attempt will fail again (at least the second token check as described) until you clear the cookies/cache and try again. I hope this helps a bit in understanding. Thanks for your help!
bobbyiliev

Sep 24th, 2023 07:37 AM

Hi there,

This is a very interesting edge-case, I don't have an Android phone to test this out with at the moment, but will try to get one and look into this further.

In the meantime, does this happen on all login pages? For example if you try to login via the Voyager /admin page, do you see the same behaviour or is it only for the customer login at /login?

Also does this happen with both the Tailwind CSS theme and the TALL stack themes or only with one of them?

Thanks again for reporting the problem!

patrickkoehli93

Sep 28th, 2023 06:47 AM

Hi Bobby We tested it on the Voyager /admin page too and the behavior was the same. We only ran the tests with the TALL stack theme... Since we figured out that the auto-fill also auto-submits the form, we came up with a possible solution: We disabled the submit-button right after the login was submitted. So far, the error didn't occur anymore but we're still checking it every now and then. This is probably not the prettiest solution, but I wouldn't exactly have known where to handle the exception when more than one POST request is sent to the login page in succession.

// Get login form
const loginForm = document.getElementById('login-form');

// Check if login form has been submitted
loginForm.addEventListener('submit', function(e) {
    e.preventDefault();

    // Get the submit button
    const submitBtn = document.getElementById('submit-btn');

    // Disable the submit button
    submitBtn.disabled = true;

    // Submit the form
    this.submit();
});