S
SolidJS6mo ago
Liquido

With Solid Auth template, I get "UnknownAction: cannot parse action at /api/auth/session"

I am using the Solid Start with Auth template and created a server action form form submission
import { getSession } from "@solid-mediakit/auth";
import { action } from "@solidjs/router";
import { getRequestEvent } from "solid-js/web";

const submitCreateAction = action(async function createAction(
formData: FormData
) {
"use server";

const event = getRequestEvent();
if (!event) throw new Error("No request event");

const session = await getSession(event.request, authOptions); // <-- This line causes the error
if (!session?.user?.id) throw new Error("Not logged in");

const userId = session.user.id;
const name = formData.get("name");

if (!name) throw new Error("Input is empty");

console.log("Name", name);
console.log("User ID", userId);
});


function CreatePage() {
return (
<form method="post" action={submitCreateAction}>
<label for="name">Name</label>
<input
type="text"
name="name"
id="name"
placeholder="Enter name"
/>
<button type="submit">Create</button>
</form>
);
}

export default requireAuth(CreatePage);
import { getSession } from "@solid-mediakit/auth";
import { action } from "@solidjs/router";
import { getRequestEvent } from "solid-js/web";

const submitCreateAction = action(async function createAction(
formData: FormData
) {
"use server";

const event = getRequestEvent();
if (!event) throw new Error("No request event");

const session = await getSession(event.request, authOptions); // <-- This line causes the error
if (!session?.user?.id) throw new Error("Not logged in");

const userId = session.user.id;
const name = formData.get("name");

if (!name) throw new Error("Input is empty");

console.log("Name", name);
console.log("User ID", userId);
});


function CreatePage() {
return (
<form method="post" action={submitCreateAction}>
<label for="name">Name</label>
<input
type="text"
name="name"
id="name"
placeholder="Enter name"
/>
<button type="submit">Create</button>
</form>
);
}

export default requireAuth(CreatePage);
This is the error keep getting on the server side:
[auth][error] UnknownAction: Cannot parse action at /api/auth/session. Read more at https://errors.authjs.dev#unknownaction
My goal is to get the userId from the session object. What am I doing wrong here?
Auth.js | Errors
Authentication for the Web
7 Replies
Liquido
LiquidoOP6mo ago
After some digging, I found out that the reason why I get error here is due to usage of solid server actions. If I use cache method to fetch data, everything works as expected. Is there a workaround to get the session working with actions? My main goal is to not pass the user id via form data but retrieve it from the session id
peerreynders
peerreynders6mo ago
Your core issue seems to be that you want to return a result from an action. That is what useSubmission is for. Provided you return something from the action function that data (provided Seroval can serialize it) appears as submission.result as soon as submission.pending transitions from true to false. If you throw an Error it will appear as submission.error instead. Once you are done with the result/error it's a good habit to submission.clear() so that it won't resurface unexpectedly later as the “most recent submission with a result or error”. Actions returning undefined clear themselves.
GitHub
GitHub - lxsmnsyc/seroval: Stringify JS values
Stringify JS values. Contribute to lxsmnsyc/seroval development by creating an account on GitHub.
Liquido
LiquidoOP6mo ago
Why would that make getting the session fail? I tried it out with useSubmission and I am still getting the same error. The getSession method in the solidjs-mediakit/auth package fails
peerreynders
peerreynders6mo ago
I didn't see that this was about mediakit. The first thing I would try:
const session = await getSession(event.nativeEvent.node.req, authOptions);
const session = await getSession(event.nativeEvent.node.req, authOptions);
H3 event.node
Event Object - h3
Event object carries an incoming request and context.
Liquido
LiquidoOP6mo ago
I had to dig deep into the code of mediakit and figure out where the error is originating from and why and at the end I figured out the problem. I am using the mediakit auth package, which uses @auth/core internally. So, basically, when I call getSession(event.request, authOptions) , Auth.js extracts the "Auth Action" by removing the basePath from the URL. When calling the getSession from cache method, the basePath = /api/auth. So, if the request URL is /api/auth/session, Auth.js would evaluate it to "session" action. (Link to the Regex: https://github.com/nextauthjs/next-auth/blob/97ad36187eea613d209c8a1d6da98ccdf3c93df7/packages/core/src/lib/utils/web.ts#L122) However, for some reason, when using server actions, basePath config property is not sent to Auth.js and the default value for basePath in Auth.js is hardcoded to /auth. As a result, the Regex that should extract the action fails. As I was following the trace upwards, the mediakit just passes the authOptions to Authjs and Authjs uses the basePath from config to determine the action. So, I fixed this issue by providing basePath in my authOptions:
export const authOptions : SolidAuthOptions = {
// ...
basePath: '/api/auth'
}
export const authOptions : SolidAuthOptions = {
// ...
basePath: '/api/auth'
}
This solves the issue and server actions can retrieve the session data now. However, it is still a mystery to me that calling the same method with the same options inside cache works as expected. When I was debugging it, without explicitly defined basePath, I could see the value from inside Authjs when getSession is called from cache... Now that I am thinking about it, is it possible that the mediakit auth library mutates the auth options when the routes are created, which works during cache because routes are initialized and the async op is triggered by component. But that does not happen for server actions because they dont need router at all.
peerreynders
peerreynders6mo ago
it is still a mystery to me that calling the same method with the same options inside cache works as expected.
What are you doing inside the function passed to cache? Perhaps irrelevant but 'use server' code has something like a _server (or something like that) based URL-not knowing Auth I don't know if that has an impact when there only is a partial configuration.
Liquido
LiquidoOP6mo ago
I actually did the same thing but instead of action, I used cache and createAsync. Btw my hunch about the mediakit auth modifying the auth options was correct. The SolidAuth function that is provided by mediakit mutates the config object (i.e auth options) on handler, signIn, and signOut: - https://github.com/solidjs-community/mediakit/blob/main/packages/auth/solid/src/index.ts#L27 - https://github.com/solidjs-community/mediakit/blob/main/packages/auth/solid/src/utils.ts#L76
Want results from more Discord servers?
Add your server