Re: Reloading XSRF token on browser 'back' button?

"John P. Rouillard" <[email protected]> Wed, 04 Dec 2024 14:00:29 -0500
Newsgroups gmane.comp.bug-tracking.roundup.user
Message-ID <[email protected]>
Hi Ralf:

In message <[email protected]>,
Ralf Schlatterbeck writes:
>I'm currently experiencing problems with users hitting the browser
>'back' button. Currently the double-submission javascript prevents the
>page from being submitted again (resulting in the message "please be
>patient").  A user complains that she's been patient for weeks now :-)

That's a good user to hang on to 9-).

Question: why is she hitting the back button?

If she is using a item (issue123, user2 ...) form, it should leave her
at the same page she started on. Going back would show the same page
but with an empty form since the form data was used to update the
item. This issue might be resolved by changing the steps in the
workflow.

>I can easily fix this by resetting the 'submitted' variable on page load
>(which is, fortunately, also triggered on browser 'back' button).

This isn't relevant to this issue, but I have wanted the back button
to reset after a few seconds (in cases where connectivity failed). To
do this, I disable the button, change the text to "submitting") and
set up a function to reset the button to a clickable state using
setTimeout().

>But the XSRF token has already been used and we get an error on the second
>submission.
>Now the user can just submit again (because the page with the error now
>has a new XSRF token) but they might give up

On load you can tell that the the form has been submitted by the
submitted variable/button state. Also you can tell if this navigation
is a "back" navigation by using:

   https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming/type

to look for back_forward.

Then you can you pop up a message:

  This page has been submitted already. For security, you need to
  refresh the page before submitting it again. [refresh page]

where refresh page does a location.reload(). Alternatively just do the
reload automatically under these conditions.

>(losing all data entered into the form).

Well the data has already been committed so I am not sure its loss is
an issue. But I am not sure what the workflow is here. Also when using
the back button, I am not sure if the data represents the current
state on the server.

>Is there an easy way to obtain a new XSRF token when the user hits
>the 'back' button (I can detect this condition by checking the
>'submitted' javascript variable).

If the user has consumed the XSRF/CSRF token/nonce, the only way to
generate a new one is to reload the page from the server.

The CSRF nonce is unique per connection and is only supposed to be
used when that specific page is submitted. Once it is used, a new
valid nonce has to be minted on the server. The location.refresh()
method should force a reload and minting of a new nonce.  This might
wipe any locally entered data present in the page though.

If preserving form data on the 'back' page is required, I think you
can store all the form data in session storage to using
FormData(formDomElement)
(https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest_API/Using_FormData_Objects). You
could also look at a form serializer javascript library.

IIRC, you can't restore file input data from javascript. It requires
the user to reselect the files.

After the refresh (which should have type==reload rather than
back_forward), check to see if stored data for that url is present and
restore it (skipping the @csrf field if you didn't delete it before
storing). Some ideas are found at:

https://dev.to/jmjkim/how-to-keep-input-values-even-after-reloading-your-browser-4mm5

https://darekkay.com/blog/preserve-form-values/

https://www.johnkieken.com/how-to-handle-an-expired-csrf-token-after-a-page-is-left-open/

https://strapdownjs.com/window-reload-javascript/

Thoughts?

--
				-- rouilj
John Rouillard
===========================================================================
My employers don't acknowledge my existence much less my opinions.