SvelteKit + supabase 세션 만료 처리

Beaver Bridge - Oct 25 '23 - - Dev Community

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;
      ...
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
// hooks.server.js
import { DateTime } from "luxon";

export const handle = async ({ event, resolve }) => {
  event.locals.user_last_activity_at = DateTime.now().toISO();
  ...
}
Enter fullscreen mode Exit fullscreen mode

hooks.server.js 는 화면이 호출될 때마다 호출이 되기 때문에 여기서 마지막 활동 시간을 저장한다.

// +layout.server.js
return {
  user_last_activity_at: locals.user_last_activity_at,
  ...
}
Enter fullscreen mode Exit fullscreen mode
// +layout.js
return {
  user_last_activity_at: data.user_last_activity_at,
  ...
}
Enter fullscreen mode Exit fullscreen mode
// +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>
Enter fullscreen mode Exit fullscreen mode

SvelteKit은 기본 설정이 data-sveltekit-preload-data="hover"라서 링크에 마우스 커서만 올려도 백그라운드에서 호출을 해버린다. 그래서 다른 걸 하기 전에 세션 만료 처리를 할 수 있다.

다만 여전히 문제는 있는데, 작성에 30분 이상 걸리면 저장하기 전에 로그인이 종료된다. 사용자들이 잘 알아서 써주겠지...

. . . . . . . . . . . . . . . . . . . . . . . . . . .