putyourlightson / craft-sprig

A reactive Twig component framework for Craft CMS.
https://putyourlightson.com/plugins/sprig
MIT License
125 stars 9 forks source link

Handling frequent 400/401/403 errors in multi-step forms #365

Closed romainpoirier closed 2 months ago

romainpoirier commented 5 months ago

Support Request

I am using Sprig (2.8.0) for multi-step forms that are only accessible to logged-in users.

The action of these forms goes to module controllers, starting with:

$this->requireSiteRequest()

I frequently receive the following types of 400/401/403 errors in the logs, which seem to be related to Sprig (refs to craft-sprig-core):

[web.ERROR] [yii\web\HttpException:400] Unable to verify your data submission. {"trace":[...],"memory":4002400,"exception":"[object] (yii\web\BadRequestHttpException(code: 0): Unable to verify your data submission. at /www/vendor/yiisoft/yii2/web/Controller.php:220)"}
[web.ERROR] [yii\web\HttpException:401] Your request was made with invalid credentials. {"trace":[...],"memory":3868488,"exception":"[object] (yii\web\UnauthorizedHttpException(code: 0): Your request was made with invalid credentials. at /www/vendor/yiisoft/yii2/filters/auth/AuthMethod.php:93)"}
[web.ERROR] [yii\web\HttpException:403] {"trace":[...],"memory":2580328,"exception":"[object] (yii\web\ForbiddenHttpException(code: 0):  at /www/vendor/craftcms/cms/src/web/Controller.php:205)"}

Assumption: Some users keep form pages open in their browsers. Sometimes, they submit a form page while their session has expired (after one hour, as specified by userSessionDuration in the Craft CMS documentation here).

However, according to the Sprig documentation (link):

If set to post, Sprig automatically sends a CSRF token in the request.

In theory, I should not need to configure anything else: the duration of the CSRF token sent by Sprig should match the ongoing user session.

Is it normal to regularly receive these 400 errors? How can I prevent this?

Plugin Version

2.8.0

bencroker commented 5 months ago

Do those errors only appear in the logs, or can you reproduce them? That 400 error, for example, is due to CSRF protection kicking in, so it may be caused by spam bots submitting the form. For the other errors, I’d need to see the full stack trace.

bencroker commented 2 months ago

Closing due to inactivity.

romainpoirier commented 2 months ago

Apologies for the delayed response, I was busy with the project launch.

The Sprig form is only accessible to logged-in Craft users, preventing spam bots from creating it. Despite this, some users report errors, but there’s no clear pattern.

I cannot reproduce these errors, which complicates debugging. However, the issues have been reported by several users.

Users are authenticated through a Controller using the following code:

$user = Craft::$app->users->getUserById($userId);
Craft::$app->user->login($user, 3600);

Below are recent examples of 400 and 403 errors. Since the site is in production, more detailed stack traces are unavailable.

Error 400:

Error 403:

bencroker commented 2 months ago

This does sound like a timeout issue. Have you considered increasing the value of userSessionDuration?

You can also gracefully handle those errors by listening for the htmx:responseError event in the template that contains the Sprig component.

<div id="error" class="hidden">
   An error occurred.
</div>

{% js %}
    htmx.on('htmx:responseError', function(event) {
        htmx.find('#error').toggleClass('hidden');
    });
{% endjs %}
romainpoirier commented 2 months ago

Currently, userSessionDuration is set to the default value of 1 hour.

I considered increasing userSessionDuration, but it doesn't seem useful or necessary. For security reasons, the session duration for this project should not be extended.

Additionally, we received support requests from users who were blocked during a subsequent step of the form. This suppose that these users did not wait long between starting and completing the submission after logging in.

I will consider using htmx:responseError to at least display an error message to these users. However, this may not resolve the issue on their next attempt.

Is there anything else we can investigate? Thank you.

bencroker commented 2 months ago

Unless you can replicate the error, I’m not sure what else to suggest.