-
-
Save Mlocik97/c6861d9ce88849b96e394a5f19dc81f7 to your computer and use it in GitHub Desktop.
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 | |
} |
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.
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.
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.