Найти тему
Nuances of programming

Как добавить аутентификацию Supabase к приложению на Vue

Оглавление

Источник: Nuances of Programming

Курс SkillFactory Frontend-разработчик PRO. Получите перспективную творческую профессию. Изучите JavaScript и TypeScript. Выполните 13 проектов в портфолио.

В этой статье мы рассмотрим, как настроить аутентификацию с помощью 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, дам ему надежный пароль, а затем выберу регион “Запад США (Северная Калифорния)”, потому что он ближе всего ко мне.

Как только настройка проекта завершится, перейдите в раздел “Аутентификация” -> “Настройки” и отключите опцию “Включить подтверждение по электронной почте”. Так будет удобнее в рамках этого руководства.

-2

Настройка 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.

Компонент Hello World, который отображается после регистрации
Компонент Hello World, который отображается после регистрации

Как выйти из системы

Это довольно просто. Внутри компонента 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”.

-5

Создайте в папке компонентов новый файл с именем 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>

Теперь страница авторизации по умолчанию должна выглядеть следующим образом:

-6

И так, если пользователь нажимает на кнопку “Войти по волшебной ссылке”:

-7

Если вы введете адрес электронной почты и нажмете “Войти”, то должны получить письмо с волшебной ссылкой. Нажмите на эту ссылку, и вы будете перенаправлены в приложение как авторизованный пользователь, где увидите экран HelloWorld.

Вывод

Supabase упрощает настройку аутентификации. Также он обеспечивает аутентификацию с помощью Google, Apple, Github и многих других провайдеров.

Читайте также:

Читайте нас в Telegram, VK

Перевод статьи Brian Barrow: How to Add Supabase Authentication to a Vue App