kit
kit copied to clipboard
`use:enhance` compatibility on form whose action isn't a SvelteKit action
Describe the problem
An unhelpful error message presents itself when we have a form with use:enhance
posting to an ordinary POST endpoint instead of a SvelteKit action. This occurs because the enhance action tries to parse the fetch response body as a JSON. If that succeeds, it looks for a data
property and attempts to parse it as JSON too, which can throw an error. If there is no data
property, submitting the form results in nothing happening, which can be confusing.
https://stackblitz.com/edit/sveltejs-kit-template-default-nmxvlc?file=src%2Froutes%2F%2Blayout.svelte
Describe the proposed solution
Maybe we can handle the outcome better or have a dev-only warning when this occurs?
Alternatives considered
Document that use:enhance
should only be used with SvelteKit actions
Importance
nice to have
Additional Information
No response
strange that when i downloaded the code and used it inside playgrounds
by replacing the @sveltejs/kit
and adapter-node
versions with workspace:*
, the page got redirected to /somewhere
instead of showing the error on same page.
Yes! Can we please go with the option of "Alternatively, we could handle the non-JSON responses better" (mentioned in the StackBlitz link). For me, this actually is somewhat urgent, not a nice-to-have. Here's the background of my use case:
I'm working with an open source authentication solution called SuperTokens
, and I'm intentionally doing auth on the backend (not the fronted) because it's more secure. In the authentication model of SuperTokens, they have short-lived Access Tokens that can be refreshed with long-lived Refreshed Tokens when the user makes requests to a server. When supporting users with or without JS in Remix, I'm able to handle this model just fine. In SvelteKit, things break. Here's the specific scenario that breaks...
Note: The /auth/session/refresh
route is a regular API route since there's no <form>
associated with it.
The Scenario
Imagine a user is on a page that displays new data on the current screen depending on what they submit to the server. This is a perfect use case for use:enhance
. Everything will work fine for a non-JS user. And JS users will be able to see the new data on the current screen without a page refresh. However, this page requires authentication.
Where SvelteKit Works
Imagine a non-JS user is on this webpage. They submit a form with an expired Access Token and a valid Refresh Token. (Note that all tokens are expressed as HTTP-only cookies.) Here's what will happen:
- The server (with the help of SuperTokens) will see that the Access Token is expired, but a Refresh Token is present. It will redirect with a
307
to/auth/session/refresh
. (This is the only route where Refresh Token HTTP-only cookies can be used and/or created, for security reasons. So there's no point in attempting a refresh on any other route.) - The server (with the help of SuperTokens) will see that a valid Refresh Token is present at the
/auth/session/refresh
route, so a new Access Token and a new Refresh Token (for security reasons) will be returned to the user as HTTP-only cookies. It will redirect back the the original POST route with a307
. - Because the non-JS users was redirected back to the original page with a 307, the POST will continue as normal. Since they are now authenticated with a valid Access Token, they will get to see the new data on the screen without having to inconveniently resubmit their form data.
Where SvelteKit Fails
Now imagine a JS user is on this webpage. They submit a form with an expired Access Token and an expired Refresh Token. Here's what will happen:
- The server (with the help of SuperTokens) will see that the Access Token is expired, but a Refresh Token is present. It will redirect with a
307
to/auth/session/refresh
. - The server (with the help of SuperTokens) will see that a valid Refresh Token is not present at the
/auth/session/refresh
route. So all of the user's Auth Cookies will be deleted by the server. Additionally, the user will be redirected to the/login
page with a303
. (By redirecting with a303
, there's no risk of inappropriately POST-ing to the/login
route. This also removes the unlikely-but-possible scenario where someone could accidentally re-authenticate as a different user during the redirect because of the values in the original form POST.) - Because the JS user was redirected to the the
/login
page with a 303, the the page's HTML is returned. - SvelteKit errors out (as shown in the StackBlitz link).
I've run into an issue today with redirect form actions and setting headers. I thought form actions would work like post server endpoint and returning a response with redirect settings would redirect but no get an error because form actions only expects data to return and using set headers redirect doesn't keep headers.
So it would be nice even with actions to be able to return redirect responses that are not data to or from form.
I've run into an issue today with redirect form actions and setting headers. I thought form actions would work like post server endpoint and returning a response with redirect settings would redirect but no get an error because form actions only expects data to return and using set headers redirect doesn't keep headers.
So it would be nice even with actions to be able to return redirect responses that are not data to or from form.
Do you mind elaborating on this with a code example?
I've run into an issue today with redirect form actions and setting headers. I thought form actions would work like post server endpoint and returning a response with redirect settings would redirect but no get an error because form actions only expects data to return and using set headers redirect doesn't keep headers.
So it would be nice even with actions to be able to return redirect responses that are not data to or from form.
Do you mind elaborating on this with a code example?
I can make a repo later and share, no problem.
@JonathonRP is the issue that you're talking about similar to what's shown in the StackBlitz link in the OP? Or is it something different?
@ITenthusiasm similar, I'm using form actions with use enhance and also not working if I return a response that doesn't have data prop or is sveltekit redirect(), I'm attempting to have redirect and settings authorization header.
@eltigerchino, repo - https://stackblitz.com/~/github.com/JonathonRP/sveltekit-authjs-redirect_demo?initialPath=/linkBuxferAccount check /src/routes/linkBuxferAccount/+page.server.ts