Skip to content

Commit

Permalink
Merge pull request #55 from intuitem/fix/frontend-session-timeout
Browse files Browse the repository at this point in the history
Fix/frontend session timeout
  • Loading branch information
eric-intuitem authored Feb 16, 2024
2 parents ed21cac + 0209b58 commit ebd87fc
Showing 1 changed file with 34 additions and 48 deletions.
82 changes: 34 additions & 48 deletions frontend/src/hooks.server.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,30 @@
import { BASE_API_URL } from '$lib/utils/constants';
import type { User } from '$lib/utils/types';
import { redirect, type Handle, type HandleFetch } from '@sveltejs/kit';
import { redirect, type Handle, type RequestEvent, type HandleFetch } from '@sveltejs/kit';

const LOGIN_REQUIRED_ROUTING_GROUP = new Set(['app']); // List of route group that require login to be accessed
const ROUTE_GROUP_REGEX = /^\([a-zA-Z0-9_]+\)/;

export const handle: Handle = async ({ event, resolve }) => {
const route: string | null = event.route.id;
let group = null;

const session = event.cookies.get('sessionid');

if (route) {
group = route.substring(1).match(ROUTE_GROUP_REGEX)?.[0];
group = group?.substring(1, group.length - 1);
}
if (!session && group && LOGIN_REQUIRED_ROUTING_GROUP.has(group)) {
redirect(302, `/login?next=${event.url.pathname}`);
}

let csrfToken = event.cookies.get('csrftoken');
async function ensureCsrfToken(event: RequestEvent): Promise<string> {
let csrfToken = event.cookies.get('csrftoken') || '';
if (!csrfToken) {
csrfToken = await fetch(`${BASE_API_URL}/csrf/`, {
const response = await fetch(`${BASE_API_URL}/csrf/`, {
credentials: 'include',
headers: {
'content-type': 'application/json'
}
})
.then((res) => res.json())
.then((res) => res.csrfToken);
headers: { 'content-type': 'application/json' }
});
const data = await response.json();
csrfToken = data.csrfToken;
event.cookies.set('csrftoken', csrfToken, {
httpOnly: false,
sameSite: 'lax',
path: '/',
secure: true
});
}
event.cookies.set('csrftoken', csrfToken!, {
httpOnly: false,
sameSite: 'lax',
path: '/',
secure: true
});
return csrfToken;
}

if (event.locals.user) {
// There is already a logged-in user. Load page as normal.
return await resolve(event);
}

if (!session) {
// There is no session, so no logged-in user. Load page as normal.
return await resolve(event);
}
async function validateUserSession(event: RequestEvent): Promise<User | null> {
const session = event.cookies.get('sessionid');
if (!session) return null;

// Fetch the user corresponding to the session.
const res = await fetch(`${BASE_API_URL}/iam/current-user/`, {
credentials: 'include',
headers: {
Expand All @@ -57,14 +34,23 @@ export const handle: Handle = async ({ event, resolve }) => {
});

if (!res.ok) {
console.log('bad response:', await res.text());
// The session is invalid. Load page as normal.
return await resolve(event);
event.cookies.delete('sessionid', {
path: '/'
});
redirect(302, `/login?next=${event.url.pathname}`);
}
return res.json();
}

// User exists, set `events.locals.user` and load page.
const response: User = (await res.json()) as User;
event.locals.user = response;
export const handle: Handle = async ({ event, resolve }) => {
await ensureCsrfToken(event);

if (event.locals.user) return await resolve(event);

const user = await validateUserSession(event);
if (user) {
event.locals.user = user;
}

return await resolve(event);
};
Expand Down

0 comments on commit ebd87fc

Please sign in to comment.