I have a login
route that looks as follows:
import {
Title,
createCookieSessionStorage,
parseCookie,
useNavigate,
useServerContext,
} from "solid-start";
import styles from "./login.module.css";
import { A, useRouteData } from "@solidjs/router";
import {
createServerAction$,
createServerData$,
redirect,
} from "solid-start/server";
import { TOKEN_KEY } from "~/constants";
import { ErrorType, MeType } from "~/types";
import { Component, createEffect } from "solid-js";
export const routeData = () => {
return createServerData$(async (_, event) => {
const cookies = parseCookie(event.request.headers.get("Cookie") ?? "");
const token = cookies[TOKEN_KEY] ?? "";
const res = await event.fetch("http://127.0.0.1:3001/auth/me", {
headers: {
Authorization: `Bearer ${token}`,
},
credentials: "include",
});
const { me }: { me: MeType | null } = await res.json();
return {
me,
};
});
};
const Login: Component<{}> = () => {
const { latest } = useRouteData<typeof routeData>();
const nav = useNavigate();
createEffect(async () => {
if (!!latest?.me) {
nav("/", { replace: true });
}
});
const storage = createCookieSessionStorage({
cookie: {
name: "session",
secure: false,
secrets: ["je"],
sameSite: "lax",
path: "/",
maxAge: 60 * 60 * 24 * 30, // 30 days
httpOnly: true,
},
});
const [submitting, { Form }] = createServerAction$(
async (form: FormData, { request, fetch }) => {
const _data: { email: string; password: string } = {
password: form.get("password") as string,
email: form.get("email") as string,
};
const res = await fetch("http://127.0.0.1:3001/auth/login", {
credentials: "include",
body: JSON.stringify({
..._data,
}),
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
});
const data: {
user: MeType | null;
error: ErrorType | null;
jwt: string | null;
} = await res.json();
if (data.user && data.jwt) {
throw redirect("/");
}
return { data };
}
);
return (
<main>
<Title>Login</Title>
<div class={styles.login}>
<Form>
<img alt="logo" src="/icon.png" />
<h1>Login</h1>
<input name="email" type="email" placeholder="email" />
<input name="password" type="password" placeholder="password" />
<div class={styles.error}>
{submitting.result?.data.error?.field &&
submitting.result.data.error.message}
</div>
<button type="submit">Login</button>
<p>
Already have an account? <span></span>
</p>
<A href="/auth/login">Login</A>
</Form>
</div>
</main>
);
};
export default Login;
I have an authentication server that returns me a jwt token on succesfull authentication. But how can i store that token in the cookie. Ivé tried to read the docs and follows example but seems like they are not working https://start.solidjs.com/advanced/session.
Using solid-start, on the server, you can use a SessionStorage.
import { createCookieSessionStorage } from 'solid-start';
const storage = createCookieSessionStorage({
cookie: {
name: "session",
secure: process.env.NODE_ENV === "production",
secrets: [process.env.SESSION_SECRET],
sameSite: "lax",
path: "/",
maxAge: 60 * 60 * 24 * 30, // 30 days
httpOnly: true
}
});
Then, you can create a cookie like so:
async function login(request: Request, userId: string) {
const session = await storage.getSession(request.headers.get("Cookie"));
session.set("userId", userId);
const response = new Response("Logged in", {
headers: {
"Set-Cookie": await storage.commitSession(session)
}
});
}
You can simply set cookies using any JavaScript package, or do it directly which might look something like this:
document.cookie = `${YOUR_COOKIE_NAME}=; expires=Thu, 01 Jan 2024 00:00:00 UTC; domain=${YOUR_DOMAIN}; path=/; secure;`;
You can also use Solid's remote-procedure style calls to simply call a function and have it always run on the server. This adds some latency just to set a cookie by it may be the right choice depending on what you are doing. To do that, you can use createServerAction$
. That might look something like this:
createServerAction$(async (form: FormData, { request }) => {
const session = await storage.getSession(request.headers.get("Cookie"));
session.set("userId", userId);
const response = new Response("Logged in", {
headers: {
"Set-Cookie": await storage.commitSession(session)
}
});
}