Skip to content

Instantly share code, notes, and snippets.

@Mlocik97
Last active March 2, 2024 18:03
Show Gist options
  • Save Mlocik97/c6861d9ce88849b96e394a5f19dc81f7 to your computer and use it in GitHub Desktop.
Save Mlocik97/c6861d9ce88849b96e394a5f19dc81f7 to your computer and use it in GitHub Desktop.
example (writen by hand, not tested) of auth in SvelteKit. (deprecated)
export async function handle({ event, resolve }) {
const cookies = await cookie.parse(event.request.headers.get('cookie') || '');
if (event.url.pathname == '/login') {
// skip verifying user, and allow to load website
const response = await resolve(event);
return response;
}
const user = DB.User.findOne({session: cookies.token});
if (!user) {
return new Response(null, {
status: 302,
headers: {
location: '/login'
}
})
}
event.locals.user = user; // put user data to locals, it will be avaiable for getSession hook and endpoints
const response = await resolve(event);
response.headers.set({
'set-cookie': cookie.serialize('token', cookies.token, { // reset expire to 7 days
httpOnly: true,
path: '/',
maxAge: 7 * 24 * 60 * 60 // 1 week
})
})
return response;
}
export async function getSession(event) {
return event.locals.user ? {
// put here some data from event.locals.user that you wish to expose for specific user (will be aviable in Session store on client-side)
} : {}
}
export async function post({ request }) {
const formData = await request.formData();
const data = Object.fromEntries(formData);
const user = DB.User.findOne({ email: data.email });
const verified = bcrypt.compare(user.passwordHash, data.password);
if (verified) {
// set cookie, save cookie token to DB, and return response
}
return { status: 300 } // or resp. unauthorized, you can redirect to login page again
}
@fredguth
Copy link

Would you put these files in $lib? Why not make authentication be a store? The way I see stores, they are singleton services. In this way, authentication could/should be a store.

@Mlocik97
Copy link
Author

Mlocik97 commented Apr 27, 2022

those are server-side files... hooks.js is hook, while login.js is endpoint... for client-side I just then use $session store where I have populated data from getSession hook. And ofc cookies... That's all where I have user's data and token. Then based on value in locals I set in handle hook, I can verify user's role or permissions to do specific action by just putting if (locals.user.permission.delete_messages) and do logic in it, else, return "Permission denied" message. On client-side it's simple, there I use just forms or fetch with "credentials: 'include'" option, and as it pass cookie token to request object on server-side (handle hook), you can verify user as I do in example. On client-side to show only specific things for specific user I just do:

{#if $session.user.permissions.delete_messages)
    <DeleteButton>
{/if}

you don't need to worry about if it's safe, as on server-side, you already check for permissions in specific endpoint if user can do specific action. So even if they change through browser console $session content, it will not allow them delete messages.

@Mlocik97
Copy link
Author

Mlocik97 commented Sep 11, 2022

This example is actually deprecated,... now there is more elegant way with build-in cookie.set. No more need of cookie module.

So instead:

export async function handle({ event, resolve }) {
    const cookies = await cookie.parse(event.request.headers.get('cookie') || '');
    // somewhere else in code `cookies.token`.

you can write just simple

export async function handle({ event, resolve }) {
    const token = event.cookies.get('token');

Same for setting cookies. There are also few other stuff that can be simplified. Will write new example when I will have time.

Btw. getSession was removed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment