В этой статье мы рассмотрим, как настроить аутентификацию с помощью Supabase и Vue 3.
Описанный метод подходит и для Vue 2, но понадобится изменить настройки, чтобы работать с API Options. Я же пользуюсь Vue 3, поскольку теперь это версия по умолчанию.
Здесь не будет уделено много внимания стилю программирования. В основном сосредоточимся на аутентификации поверх базы данных.
Требования
Вам нужно быть знакомым с JavaScript и иметь опыт работы с Vue 3. Опыт работы с Supabase пригодится, но не обязателен.
Вам также понадобится установить на компьютер Node.js и NPM.
Начало работы
Начнем с интерфейса. В первую очередь настроим проект.
Откройте терминал и внутри папки, в которой хотите разместить проект, выполните команду:
npm init vite@latest vue-supabase-auth --template vue
Она инициализирует новый проект Vite с помощью Vue 3 в папке с именем vue-supabase-auth
.
Запустите его в редакторе кода и откройте файл App.vue
внутри папки src
. Когда я инициализировал проект, Vite поместил тег script
над тегом template
. Я решил переместить тег шаблона наверх, но в этом нет необходимости.
Добавьте аутентификацию в приложение
Следующий шаг — добавить аутентификацию в приложение. Supabase дает возможность аутентифицировать пользователя многими различными способами.
Мы рассмотрим, как настроить базовую аутентификацию по электронной почте/паролю и аутентификацию с помощью “волшебной ссылки”. “Волшебная ссылка” — это просто ссылка, отправленная на электронную почту пользователя, при нажатии на которую он попадет в приложение и войдет в систему.
Создайте учетную запись Supabase
Зарегистрируйтесь на Supabase, если еще этого не сделали.
Как только вы войдете в систему, нажмите на зеленую кнопку с надписью “New project” (“Новый проект”) и выберите организацию по умолчанию, которая была создана при входе в систему. Моя называлась “Организация Брайанбэрроу” (по моему имени).
После появится окно, где вы предоставите некоторую информацию о проекте. Я назову его basic-auth, дам ему надежный пароль, а затем выберу регион “Запад США (Северная Калифорния)”, потому что он ближе всего ко мне.
Как только настройка проекта завершится, перейдите в раздел “Аутентификация” -> “Настройки” и отключите опцию “Включить подтверждение по электронной почте”. Так будет удобнее в рамках этого руководства.
Настройка Supabase в проекте Vue
Во-первых, нам нужно запустить npm install @supabase/supabase-js
, чтобы получить пакет JavaScript для интеграции с Supabase.
Затем нужно создать файл supabase.js
в папке src
проекта. Он должен содержать следующее:
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
В приведенном выше коде нужно настроить переменные среды, которые содержат ключи Supabase. Создайте файл env.local
в корне проекта и добавьте VITE_SUPABASE_URL
и VITE_SUPABASE_ANON_KEY
. Вы можете найти свой URL-адрес и anon_key на панели инструментов проекта Supabase.
Файл env.local
будет выглядеть так:
VITE_SUPABASE_URL=YOUR_SUPABASE_URL
VITE_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY
Мы также создадим центральное хранилище для данных, которые необходимы во всем приложении (например, информация о пользователе). Создайте файл store.js
в папке src
и заполните его этим кодом:
import { reactive } from "vue";
export const store = {
state: reactive({
user: {},
}),
};
Создание компонентов входа и регистрации
Проверка подлинности на Supabase разделяет процессы входа и регистрации, поэтому нам нужно обрабатывать их по-разному. Для ясности я решил создать два отдельных компонента.
Создайте файл SignUp.vue
в папке components
и добавьте следующий код:
<template>
<div>
<h2>Sign up for an account</h2>
<form @submit.prevent="handleSignup">
<div>
<label for="email">Email</label>
<input id="email" type="email" v-model="email" />
</div>
<div>
<label for="password">Password</label>
<input id="password" type="password" v-model="password" />
</div>
<div>
<button type="submit">Sign up</button>
</div>
</form>
</div>
</template>
<script>
import { ref } from "vue";
import { supabase } from "../supabase";
export default {
setup() {
const email = ref("");
const password = ref("");
const handleSignup = async () => {
try {
// Задействуем предоставленный Supabase метод для обработки регистрации
const { error } = await supabase.auth.signUp({
email: email.value,
password: password.value,
});
if (error) throw error;
} catch (error) {
alert(error.error_description || error.message);
}
};
return {
email,
password,
handleSignup,
};
},
};
</script>
Теперь создайте файл SignIn.vue
и добавьте туда приведенный ниже код. Единственные различия — в именах вызываемых методов, также немного отличается текст в разметке.
<template>
<div>
<h2>Sign in to your account</h2>
<form @submit.prevent="handleSignin">
<div>
<label for="email">Email</label>
<input id="email" type="email" v-model="email" />
</div>
<div>
<label for="password">Password</label>
<input id="password" type="password" v-model="password" />
</div>
<div>
<button type="submit">Sign in</button>
</div>
</form>
</div>
</template>
<script>
import { ref } from "vue";
import { supabase } from "../supabase";
export default {
setup() {
const email = ref("");
const password = ref("");
const handleSignin = async () => {
try {
// Задействуем предоставленный Supabase метод для обработки входа
const { error } = await supabase.auth.signIn({
email: email.value,
password: password.value,
});
if (error) throw error;
} catch (error) {
alert(error.error_description || error.message);
}
};
return {
email,
password,
handleSignin,
};
},
};
</script>
Теперь стоит добавить компонент-обертку над этими двумя. Создайте файл Auth.vue
и вставьте туда следующий код:
<template>
<div>
<sign-up v-if="isSignUp" />
<sign-in v-else />
<button @click="isSignUp = !isSignUp">
{{
isSignUp
? "Already have an account? Sign In"
: "Don't have an account yet? Sign Up"
}}
</button>
</div>
</template>
<script>
import { ref } from "vue";
import SignUp from "./SignUp.vue";
import SignIn from "./SignIn.vue";
export default {
components: { SignUp, SignIn },
setup() {
const isSignUp = ref(true);
return {
isSignUp,
};
},
};
</script>
<style scoped></style>
Это позволит пользователю переключаться между представлениями входа и регистрации. Теперь снова откройте App.vue
и обновите код:
<template>
<!-- Проверка доступности пользователя в хранилище; при недоступности - показываем компонент авторизации-->
<Auth v-if="!store.state.user" />
<!-- Если пользователь доступен, показываем компонент Hello World -->
<HelloWorld v-else msg="Hello Vue 3 + Vite" />
</template>
<script>
import Auth from "./components/Auth.vue";
import HelloWorld from "./components/HelloWorld.vue";
import { store } from "./store";
import { supabase } from "./supabase";
export default {
components: {
HelloWorld,
Auth,
},
setup() {
// сначала проверяем, вошел ли пользователь в систему с помощью Supabase
store.state.user = supabase.auth.user();
// затем настраиваем слушатель для обновления хранилища, если меняется пользователь - выходит из системы или входит
supabase.auth.onAuthStateChange((event, session) => {
if (event == "SIGNED_OUT") {
store.state.user = null;
} else {
store.state.user = session.user;
}
});
return {
store,
};
},
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Теперь если пользователь не вошел в систему, то у него отобразится компонент аутентификации. В противном случае отобразится HelloWorld.vue
, как мы изначально и настроили.
Зарегистрируйтесь, используя действующий адрес электронной почты и пароль. После вы должны снова увидеть компонент HelloWorld.
Как выйти из системы
Это довольно просто. Внутри компонента HelloWorld добавьте следующее в нижнюю часть тега шаблона:
<button @click="signOut">Sign Out</button>
Затем обновите тег script
в HelloWorld до этого:
<script setup>
import { ref } from "vue";
import { supabase } from "../supabase";
defineProps({
msg: String,
});
const count = ref(0);
async function signOut() {
const { error } = await supabase.auth.signOut();
}
</script>
Мы импортируем файл supabase
, созданный ранее, а затем добавляем метод выхода signOut
, который вызывается при нажатии кнопки.
Аутентификация с помощью волшебной ссылки
Supabase также предоставляет возможность отправлять на электронную почту волшебную ссылку, по которой можно кликнуть — это приводит пользователя в приложение и авторизует его. Ссылка, которую формирует Supabase, перенаправит на сайт, поэтому нужно убедиться, что в нашем распоряжении есть правильный URL-адрес перенаправления и он задан в настройках Supabase.
Перейдите на страницу “Авторизация” -> “Настройки” на панели управления Supabase для вашего проекта и убедитесь, что URL localhost указан в поле “Site URL”.
Создайте компонент MagicLink
Создайте в папке компонентов новый файл с именем MagicLink.vue
и добавьте следующий код:
<template>
<div>
<h2>Sign in With Magic Link</h2>
<form @submit.prevent="handleMagicLink">
<div>
<label for="email">Email</label>
<input id="email" type="email" v-model="email" />
</div>
<div>
<button type="submit">Sign in</button>
</div>
</form>
</div>
</template>
<script>
import { ref } from "vue";
import { supabase } from "../supabase";
export default {
setup() {
const email = ref("");
const handleMagicLink = async () => {
try {
// Мы вызываем метод входа из Supabase, чтобы отправить волшебную ссылку. Передаем ему только электронную почту.
const { error } = await supabase.auth.signIn({
email: email.value,
});
if (error) throw error;
} catch (error) {
alert(error.error_description || error.message);
}
};
return {
email,
handleMagicLink,
};
},
};
</script>
Этот компонент похож на компонент входа в систему. Он использует тот же метод, но чтобы получить волшебную ссылку, мы передаем только электронную почту.
Теперь нужно обновить Auth.vue
, чтобы он также задействовал компонент MagicLink
. Обновите Auth.vue
до следующего:
<template>
<div>
<!-- логика v-if для определения, какой компонент отображать -->
<sign-up v-if="isSignUp && !useMagicLink" />
<sign-in v-else-if="!isSignUp && !useMagicLink" />
<magic-link v-else />
<div v-if="!useMagicLink">
<button v-if="!useMagicLink" @click="isSignUp = !isSignUp">
{{
isSignUp
? "Already have an account? Sign In"
: "Don't have an account yet? Sign Up"
}}
</button>
<p>Or</p>
</div>
<button @click="toggleMagicLink">
{{
useMagicLink
? "Sign in with email and password"
: "Sign in with magic link"
}}
</button>
</div>
</template>
<script>
import { ref } from "vue";
import SignUp from "./SignUp.vue";
import SignIn from "./SignIn.vue";
import MagicLink from "./MagicLink.vue";
export default {
components: { SignUp, SignIn, MagicLink },
setup() {
const isSignUp = ref(true);
const useMagicLink = ref(false);
function toggleMagicLink() {
useMagicLink.value = !useMagicLink.value;
}
return {
isSignUp,
useMagicLink,
toggleMagicLink,
};
},
};
</script>
<style scoped></style>
Теперь страница авторизации по умолчанию должна выглядеть следующим образом:
И так, если пользователь нажимает на кнопку “Войти по волшебной ссылке”:
Если вы введете адрес электронной почты и нажмете “Войти”, то должны получить письмо с волшебной ссылкой. Нажмите на эту ссылку, и вы будете перенаправлены в приложение как авторизованный пользователь, где увидите экран HelloWorld.
Вывод
Supabase упрощает настройку аутентификации. Также он обеспечивает аутентификацию с помощью Google, Apple, Github и многих других провайдеров.
Читайте также:
- Какие нововведения для веб-разработки представит Vue 3.0?
- Как правильно зарегистрировать плагин в nuxt.js
- Обновления в Nuxt JS 2.8.0
Читайте нас в Telegram, VK и Дзен
Перевод статьи Brian Barrow: How to Add Supabase Authentication to a Vue App