인증 구현은 대부분의 프로젝트에서 수행하는 작업이지만 실제로 수행하는 빈도 때문에 기억으로 수행하는 방법을 기억하지 못할 수도 있습니다.
다음은 Nuxt v3로 Supabase Auth를 구현하는 방법에 대한 빠른 방법입니다. 이 예에서는 OTP를 사용하지만 모든 경우에 적용됩니다.
먼저 Supabase 웹사이트로 이동하여 프로젝트를 시작하세요.
Supabase에서 프로젝트를 생성하고 Nuxt에서 프로젝트를 시작한 후 다음을 수행하여 Supabase Nuxt 패키지를 설치하려고 합니다.
npx nuxi@latest 모듈에 supabase 추가
그런 다음 .env 파일을 생성하고 다음 환경 변수를 추가합니다.
SUPABASE_URL=<your_supabase_url> SUPABASE_KEY=<your_supabase_key>
프로젝트에 대한 Supabase 대시보드의 설정 -> API
이후에는 프로젝트를 설정할 수 있습니다. 지금까지 매우 기본적인 파일 2개를 만들었습니다:
import { defineStore } from "pinia"; export const useAuthStore = defineStore("auth", () => { const supabase = useSupabaseClient(); const sendOtp = async (email: string) => { const { error } = await supabase.auth.signInWithOtp({ email, }); if (error) { throw error; } return true; }; const verifyOtp = async (email: string, otp: string) => { const { error } = await supabase.auth.verifyOtp({ type: "email", token: otp, email, }); if (error) { throw error; } return true; }; return { sendOtp, verifyOtp, }; });
<template> <div class="max-w-md mx-auto bg-white p-8 rounded-lg shadow-md"> <h2 class="text-3xl font-bold mb-6 text-center text-gray-800">Welcome</h2> <form @submit.prevent="handleSubmit" class="space-y-6"> <div v-if="mode === 'email'"> <label for="email" class="block mb-2 font-medium text-gray-700" >Email</label > <input type="email" id="email" v-model="email" required placeholder="Enter your email" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 transition duration-200" /> </div> <div v-else-if="mode === 'code'"> <p class="mb-2 font-medium text-gray-700"> Enter the 6-digit code sent to {{ email }} </p> <input type="text" v-model="otpCode" required placeholder="Enter 6-digit code" maxlength="6" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 transition duration-200" /> </div> <UButton icon="i-heroicons-paper-airplane" size="lg" color="primary" variant="solid" :label="buttonLabel" :trailing="true" block /> </form> </div> </template> <script setup lang="ts"> import { ref, computed } from "vue"; import { useAuthStore } from "~/stores/auth"; const authStore = useAuthStore(); const email = ref(""); const otpCode = ref(""); const mode = ref("email"); const buttonLabel = computed(() => { return mode.value === "email" ? "Send One-Time Password" : "Verify Code"; }); const handleSubmit = async () => { if (mode.value === "email") { try { await authStore.sendOtp(email.value); mode.value = "code"; } catch (error) { console.log("Error sending OTP: ", error); } } else { try { await authStore.verifyOtp(email.value, otpCode.value); } catch (error) { console.log("Error verifying OTP: ", error); } } }; </script> <style scoped></style>
오류가 발생할 경우를 대비해 저는 NuxtUI도 사용하고 있습니다.
기본적으로 signInWithOtp 기능은 매직 링크를 보내기 때문에 토큰을 보내려면 Supabase 대시보드에서 이메일 템플릿을 변경해야 합니다.
이는 인증 -> 아래에 있습니다. 이메일 템플릿 -> {{ .Token }}
이제 거의 모든 것입니다. 실제 인증을 받았습니다!
로그아웃을 추가하려면 다음과 같이 이전 파일에 메소드를 추가할 수도 있습니다.
const signOut = async () => { const { error } = await supabase.auth.signOut(); if (error) { throw error; } return true; };
그러나 특정 경로를 보호하려는 경우 미들웨어를 추가할 수도 있습니다.
루트에 middleware(이름은 키)라는 폴더와 auth.ts라는 파일을 만듭니다.
그런 다음 다음과 같은 내용을 추가할 수 있습니다.
export default defineNuxtRouteMiddleware((to) => { const user = useSupabaseUser(); const protectedRoutes = ["/app"]; if (!user.value && protectedRoutes.includes(to.path)) { return navigateTo("/auth"); } if (user.value && to.path === "/auth") { return navigateTo("/"); } });
이것은 기본적으로 /app 경로를 서버로부터 보호하므로 로그인하지 않고 /app으로 이동하려고 하면 /auth로 리디렉션됩니다.
마찬가지로 이미 로그인한 상태에서 /auth를 방문하려고 하면 홈 페이지 /로 리디렉션됩니다.
이제 이를 사용하려면