supabase 라이브러리에서는 https://supabase.com/docs/reference/javascript/auth-exchangecodeforsession 이런 식으로 auth가 변경됐다
라는 것을 받을 수만 있다.
그래서인지 탭을 계속 열어놓은 상태거나 심지어 pc를 종료하고 며칠 후에 켜도 자동으로 세션을 업데이트 해버린다.
다행히 Svelte를 좀 아는 분의 도움을 받아서 브라우저가 종료됐을 때는 처리가 됐으나 여전히 탭을 계속 열어놓은 상태에서는 세션이 유지된다. 보통의 사이트처럼 세션이 만료 됐습니다. 다시 로그인하세요
같은 걸 띄워야 하는데...
이리저리 찾아봐도 딱히 방법이 없는 것 같아서 원시적인 방법으로 처리하기로 했다.
// app.d.ts
declare global {
namespace App {
interface Locals {
sb: SupabaseClient;
getSession(): Promise<Session | null>;
user_last_activity_at: Date | null;
...
}
}
}
// hooks.server.js
import { DateTime } from "luxon";
export const handle = async ({ event, resolve }) => {
event.locals.user_last_activity_at = DateTime.now().toISO();
...
}
hooks.server.js 는 화면이 호출될 때마다 호출이 되기 때문에 여기서 마지막 활동 시간을 저장한다.
// +layout.server.js
return {
user_last_activity_at: locals.user_last_activity_at,
...
}
// +layout.js
return {
user_last_activity_at: data.user_last_activity_at,
...
}
// +layout.svelte
<script>
import { beforeUpdate } from "svelte";
import { goto } from "$app/navigation";
import { DateTime } from "luxon";
export let data;
$: ({ supabase, session } = data);
let wasCallGoToLogin = false; // beforeUpdate가 여러 번 호출돼서 회피용
beforeUpdate(async () => {
const userLastActivityMinute = DateTime.fromISO(data.user_last_activity_at).diffNow("minutes").minutes;
// 마지막 활동이 30분 이상 지났을 경우 로그아웃 시킨다.
if (!wasCallGoToLogin && $page.route.id != "/login" && userLastActivityMinute < -30) {
alert("로그인이 만료되었습니다. 다시 로그인해주세요.");
wasCallGoToLogin = true;
await supabase.auth.signOut();
goto("/login");
}
});
</script>
SvelteKit은 기본 설정이 data-sveltekit-preload-data="hover"
라서 링크에 마우스 커서만 올려도 백그라운드에서 호출을 해버린다. 그래서 다른 걸 하기 전에 세션 만료 처리를 할 수 있다.
다만 여전히 문제는 있는데, 작성에 30분 이상 걸리면 저장하기 전에 로그인이 종료된다. 사용자들이 잘 알아서 써주겠지...