How to implement JWT authentication in SolidJS, without SolidStart?

I'm currently learning SolidJS for a SPA app with JWT-based auth. Right now I'm trying to implement that JWT auth but I have a lot of problems and not sure if my approach is proper. What I currently have is a <LoginPage/> that calls the API and then saves the token as a cookie.
const onSubmit: JSX.EventHandler<HTMLFormElement, SubmitEvent> = async (
event
) => {
event.preventDefault();

const res = await api.post('Auth/Login', { json: loginForm });
const json: { Token: string } = await res.json();

if (res.status !== 200) {
window.alert('Login failed!');
}

// sets a cookie with the key & value
setCookies('token', json.Token);

navigate('/app/official-games');
};
const onSubmit: JSX.EventHandler<HTMLFormElement, SubmitEvent> = async (
event
) => {
event.preventDefault();

const res = await api.post('Auth/Login', { json: loginForm });
const json: { Token: string } = await res.json();

if (res.status !== 200) {
window.alert('Login failed!');
}

// sets a cookie with the key & value
setCookies('token', json.Token);

navigate('/app/official-games');
};
Then I would try to read that cookie in a top-level route component called <AuthRedirector /> which is a root route with the app routes and auth routes as children.
import { Outlet, useNavigate } from '@solidjs/router';
import { getCookie } from '~/utils/CookieUtils';

export const AuthRedirector = () => {
const navigate = useNavigate();

const token = getCookie('token');

if (!token) {
navigate('/auth/login');
} else {
navigate('/app/official-games');
}

return <Outlet />;
};
import { Outlet, useNavigate } from '@solidjs/router';
import { getCookie } from '~/utils/CookieUtils';

export const AuthRedirector = () => {
const navigate = useNavigate();

const token = getCookie('token');

if (!token) {
navigate('/auth/login');
} else {
navigate('/app/official-games');
}

return <Outlet />;
};
These are the cookie utils:
export function getCookie(key: string) {
// gets cookie as a JSON object
const cookiesObj = getCookiesAsObject();
return cookiesObj[key];
}

export function setCookie(key: string, value: any) {
document.cookie = `${key}=${value}`;
}
export function getCookie(key: string) {
// gets cookie as a JSON object
const cookiesObj = getCookiesAsObject();
return cookiesObj[key];
}

export function setCookie(key: string, value: any) {
document.cookie = `${key}=${value}`;
}
However, this seems to only set the cookie for one path, specifically in my case /app/official-games. If I access any other /app/... route then I still get redirected to /auth/login and I check the browser's cookies and don't see cookies on these other routes. Plus, with this approach I still need to manually navigate to /app after successfully logging in
6 Replies
Utsuhoagie
Utsuhoagie7mo ago
Is this even close to a good approach? How should I implement this?
bigmistqke
bigmistqke7mo ago
Components only run once So that check inside AuthRedirector is only happening when the component is called initially You could wrap that code that checks for the cookie in an effect, but it won't re-run bc there is no signal used/cookie is not reactive
bigmistqke
bigmistqke7mo ago
But I think there is a solid primitive for that https://primitives.solidjs.community/package/storage
Solid Primitives
A library of high-quality primitives that extend SolidJS reactivity
intelligent-worker-probe
You have to set the path "/" explicitely, or the default is a subpath that can't be accessed in other paths https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies
MDN Web Docs
Using HTTP cookies - HTTP | MDN
An HTTP cookie (web cookie, browser cookie) is a small piece of data that a server sends to a user's web browser. The browser may store the cookie and send it back to the same server with later requests. Typically, an HTTP cookie is used to tell if two requests come from the same browser—keeping a user logged in, for example. It remembers st...
intelligent-worker-probe
if you are at it, I would recommend setting the following attributes as well Secure SameSite: Strict
Utsuhoagie
Utsuhoagie7mo ago
I did suspect that reactivity was a problem because I wasn't using any signals, but I wasn't sure if the browser cookie API would work out of the box somehow, there's not much to read about it. Thanks though, I'm experimenting with this package and it seems to work! I don't even need to manually navigate() after say, logging in. Though right now I'm using sessionStorage instead, but it should be fine for my app as there's no real risk (or users)