
Создание демонстрационной страницы SvelteKit с веб-компонентом и паролем для входа на сайт passkeys.eu
1. Введение
В этом сообщении блога мы рассмотрим процесс создания демонстрационной страницы для passkeys.eu с использованием SvelteKit. Мы расскажем, как создать многоразовый веб-компонент и реализовать функцию входа в систему с паролем для беспрепятственного взаимодействия с пользователем. В этом руководстве предполагается базовое знакомство со SvelteKit, HTML, CSS и JavaScript. Давайте погрузимся!
2. Настройка проекта SvelteKit
Далее мы клонируем наш демонстрационный репозиторий с готовым кодом, но если вам интересно, как бы вы настроили скелет проекта, ознакомьтесь со следующими двумя разделами. В противном случае вы можете их пропустить и продолжить со структуры репозитория.
Мы будем использовать Flowbite, библиотеку компонентов, основанную на TailwindCSS, для быстрого создания адаптивного и эстетичного пользовательского интерфейса.
Давайте начнем с установки SvelteKit. Мы собираемся использовать pnpm вместо npm, так как pnpm быстрее благодаря использованию символических ссылок для повторного использования существующих зависимостей. Чтобы установить pnpm, запустите:
npm install -g pnpm
Сделав это, мы можем установить SvelteKit и инициализировать наш проект:
pnpm create svelte@latest passkeys-demo cd passkeys-demo pnpm install
Затем нам нужно установить TailwindCSS:
pnpx svelte-add@latest tailwindcss pnpm i
Наконец, нам нужно установить библиотеку Flowbite svelte.
pnpm i flowbite flowbite-svelte classnames @popperjs/core
Наконец, мы обновим наш tailwind.config.cjs, включив в него Flowbite:
const config = {
content: [
'./src/**/*.{html,js,svelte,ts}',
'./node_modules/flowbite-svelte/**/*.{html,js,svelte,ts}'
],
theme: {
extend: {}
},
plugins: [require('flowbite/plugin')],
darkMode: 'class'
};
module.exports = config;
3. Настройка шрифтов и глобальных стилей с помощью Tailwind
Чтобы настроить некоторые стандартные шрифты и стили, которые должны быть глобальными для нашего приложения, мы можем использовать тему Tailwind. Во-первых, мы создадим раздел <svelte:head> в нашем корне +page.svelte. Это ведет себя как стандартный HTML <head>, который вы найдете в файле index.html, он содержит метаданные и позволяет включать сторонние скрипты. Мы собираемся использовать его, чтобы включить некоторые шрифты из Bunny Fonts и добавить некоторые метаданные для SEO. Добавьте это в свой +page.svelte:
<svelte:head>
<link rel="preconnect" href="https://fonts.bunny.net" />
<link href="https://fonts.bunny.net/css?family=inter:500|space-grotesk:500" rel="stylesheet" />
<title>Passkeys demo</title>
<meta name="description" content="Corbado Passkey passwordless authentication demo" />
</svelte:head>
4. Структура репозитория
Давайте сначала обсудим структуру нашей папки src:
├── lib │ ├── assets │ │ ├── apple.svg │ │ ├── auth-sample.svg │ │ ├── Corbado.png │ │ ├── devices.svg │ │ ├── europe.png │ │ ├── github.png │ │ ├── google.svg │ │ ├── microsoft.svg │ │ ├── slack.webp │ │ └── twitter.png │ ├── components │ │ ├── CheckItem.svelte │ │ └── InfoCard.svelte │ └── sections │ ├── Footer.svelte │ ├── PasskeyDemo.svelte │ ├── PasskeyExplainer.svelte │ ├── PasskeySaas.svelte │ ├── PasskeyStats.svelte │ └── PasskeyTimeline.svelte ├── routes │ ├── api │ │ ├── logout │ │ │ └── +server.ts │ │ └── register │ │ └── +server.ts │ ├── +layout.svelte │ ├── +page.server.ts │ └── +page.svelte ├── app.d.ts ├── app.html └── app.postcss static └── favicon.png
lib содержит вспомогательные файлы, такие как:
- изображение
assets - на заказ
componentsмы сделали sections, который мы используем на нашей демо-странице
routes содержит все маршруты нашего приложения, такие как
api, они эквивалентны конечным точкам API, которые вы бы имели на классическом сервере/бэкенде. Путь к конечным точкам соответствует их пути к папке.- Корневой путь к
/стройным файлам: +layout.svelteопределяет общий макет и применяет наш глобальный.postcss+page.server.tsобрабатывает логику на стороне сервера для этого конкретного маршрута (в данном случае/), например функции загрузки или действия формы.+page.svelteсодержит фактический клиентский код для отображения нашей страницы.
У нас есть корневые файлы .html и .css, которые мы можем игнорировать для целей нашего руководства. И папка static для ресурсов, таких как фавиконы.
5. Настройка веб-компонента Corbado для аутентификации по паролю
Наша демонстрационная страница содержит различные разделы, определенные в нашем файле +page.svelte:
<script lang="ts">
import Footer from '$lib/sections/Footer.svelte';
import PasskeyDemo from '$lib/sections/PasskeyDemo.svelte';
import PasskeyExplainer from '$lib/sections/PasskeyExplainer.svelte';
import PasskeySaas from '$lib/sections/PasskeySaas.svelte';
import PasskeyStats from '$lib/sections/PasskeyStats.svelte';
import PasskeyTimeline from '$lib/sections/PasskeyTimeline.svelte';
import type { PageData } from './$types';
export let data: PageData;
</script>
<svelte:head>
<link rel="preconnect" href="https://fonts.bunny.net" />
<link href="https://fonts.bunny.net/css?family=inter:500|space-grotesk:500" rel="stylesheet" />
<title>Corbado Passkey demo</title>
<meta name="description" content="Corbado Passkey passwordless authentication demo" />
</svelte:head>
<PasskeyDemo {data} />
<PasskeyExplainer />
<PasskeyTimeline />
<PasskeyStats />
<PasskeySaas />
<footer />
В этой демонстрации мы сосредоточимся на интеграции Corbado, поэтому я не буду рассказывать о том, как я оформлял и создавал эти страницы. Если вам интересно, проверьте папки src/lib/sections и src/lib/components в репозитории проекта, чтобы увидеть, как они оформлены.
5.1 Настройка вашей учетной записи и проекта Corbado
Посетите Панель разработчика Corbado, чтобы зарегистрироваться и создать свою учетную запись (вы увидите пароли при регистрации в действии!).
Когда вы окажетесь в панели разработчика, перейдите в Настройки > Учетные данные:
- Нажмите
Add New.
Здесь добавьте новый авторизованный источник, чтобы ваше локальное приложение Svelte могло отправлять запросы к Corbado API с помощью веб-компонента:
- Введите описание имени, например «Демонстрация пароля»
- Введите URL-адрес источника, в нашем случае локальный URL-адрес
http://localhost:5137.
Когда вы закончите, вам нужно будет получить идентификатор вашего проекта и создать секрет API для аутентификации с помощью бэкэнда Corbado. Перейдите на вкладку API secrets.
Скопируйте имя пользователя, щелкнув по нему, и нажмите «Добавить новый», чтобы получить новый секрет API, который вы можете скопировать. Мы добавим их в файл .env в корне нашего проекта SvelteKit:
CORBADO_API_SECRET=**** PUBLIC_CORBADO_PROJECT_ID=***
SvelteKit позволяет нам легко получить к ним доступ, используя пространство имен $env для их импорта. Переменные Env с префиксом PUBLIC_ доступны как в клиентских, так и в серверных маршрутах, в то время как те, которые по умолчанию не являются секретными, доступны только в серверных маршрутах SvelteKit.
5.2 Включение веб-компонента в наш интерфейс
Первый раздел в нашем корне +page.svelte — это PasskeysDemo. Этот раздел содержит демонстрацию нашего веб-компонента. Чтобы импортировать веб-компонент Corbado в наше приложение, все, что нам нужно сделать, это добавить svelte:head для загрузки скрипта в src/lib/sections/PasskeyDemo.svelte:
<svelte:head>
<script defer src="https://auth.Corbado.com/auth.js"></script>
</svelte:head>
Затем мы можем включить его:
<Corbado-auth
style="border: none"
project_id="{PUBLIC_CORBADO_PROJECT_ID}"
conditional="yes"
login_title="Try passkey login"
login_btn="Passkey login"
register_title="Try passkey signup"
register_btn="Passkey signup"
auto_detect_language="no"
fallback_language="en"
page="register"
>
<input name="username" id="Corbado-username" value="" required autocomplete="webauthn" />
</Corbado-auth>
Веб-компонент имеет различные служебные атрибуты для настройки, например login_title или login_btn. Что важно для вас, чтобы заставить его работать, так это атрибут project_id, куда мы передадим наш PUBLIC_CORBADO_PROJECT_ID из среды. Если вы используете редактор, такой как VSCode, с расширением Svelte, он автоматически добавит этот импорт в ваш тег .svelte <script>:
import { PUBLIC_CORBADO_PROJECT_ID } from '$env/static/public';
5.3 Настройка логики перенаправления
Веб-компонент Corbado работает, перенаправляя вас на указанную вами страницу после того, как пользователь зарегистрируется или войдет в систему. Этот URL-адрес перенаправления может быть маршрутом на стороне сервера или маршрутом клиента. В нашем случае это будет конечная точка сервера SvelteKit. Чтобы настроить наш URL-адрес перенаправления, давайте зайдем в Панель разработчика Corbado, перейдем на вкладку URL-адрес в Настройки> Общие и введите следующее:
Redirect URL: введите URL-адрес, на который должно перенаправляться ваше приложение после регистрации в веб-компоненте. В нашем случае это маршрут API SvelteKit http://localhost:5137/api/register.
Application URL: введите URL-адрес, по которому работает ваше приложение, в нашем случае это localhost:5137 локально.
«Идентификатор проверяющей стороны»: введите домен (без протокола, порта или пути), к которому должны быть привязаны пароли. В нашем случае это «localhost».
URL-адрес приложения используется, среди прочего, для того, чтобы снова правильно направлять пользователей к веб-компоненту, когда они щелкнули магическую ссылку электронной почты.
Давайте теперь добавим маршрут нашего сервера в SvelteKit. Под папкой routes/ создадим папки api/register и создадим в них файл api/register/+server.ts. Это будет содержать наш маршрут API:
import { CORBADO_API_SECRET } from '$env/static/private';
import { PUBLIC_CORBADO_PROJECT_ID } from '$env/static/public';
import { error, redirect, type RequestHandler } from '@sveltejs/kit';
export const GET = (async ({ url, request, getClientAddress, cookies }) => {
const Corbado = {
sessionToken: url.searchParams.get('sessionToken') || '',
userAgent: request.headers.get('user-agent'),
remoteAddress: getClientAddress()
};
const response = await fetch('https://api.Corbado.com/v1/sessions/verify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Basic ${btoa(`${PUBLIC_CORBADO_PROJECT_ID}:${CORBADO_API_SECRET}`)}`
},
body: JSON.stringify({
token: Corbado.sessionToken,
clientInfo: {
userAgent: Corbado.userAgent,
remoteAddress: Corbado.remoteAddress
}
})
});
if (response.status !== 200) {
throw error(401, 'Invalid session token');
}
cookies.set('jwt', crypto.randomUUID(), {
httpOnly: true,
path: '/',
sameSite: 'lax',
secure: true,
maxAge: 60 * 60 * 24 // 1 day
});
throw redirect(303, '/');
}) satisfies RequestHandler;
Давайте переварим это один за другим. Этот маршрут GET будет автоматически вызываться Corbado API, как только пользователь нажмет кнопку регистрации или входа в систему. Затем нам нужно проверить эту информацию с помощью API Corbado, а затем мы можем аутентифицировать нашего пользователя локально.
В константе Corbado мы сохраняем всю информацию, относящуюся к проверке, такую как sessionToken и clientinfo, такую как userAgent и remoteAddress. SvelteKit предоставляет полезных помощников, которые мы можем передать маршруту, чтобы получить всю эту информацию.
Получив эту информацию, мы хотим вызвать конечную точку Corbado API sessionVerify. Мы используем наш идентификатор проекта и наш секрет, который мы сохранили в нашем .env ранее, для аутентификации с помощью обычной аутентификации, а в теле мы передаем sessionToken и clientinfo, которые мы собрали.
Если наш ответ не удался, мы позволим нашей конечной точке выдать ошибку. Если мы успешно прошли проверку, теперь мы можем установить файл cookie, используя новый токен jwt, и перенаправить нашего клиента обратно в корень. Обратите внимание, что в рабочей среде вы, вероятно, использовали бы информацию о пользователе, возвращенную вам в ответ на вызов sessionVerify, для создания пользователя в вашей базе данных, но для наших целей мы просто создадим файл cookie локально.
5.4 Использование файлов cookie для управления состоянием аутентификации
Теперь, когда мы можем нажать «Зарегистрироваться» в нашем веб-компоненте и получить обратно файл cookie, нам нужно загрузить этот файл cookie в наш клиент и использовать его для отображения статуса входа. Для этого мы можем использовать функции load SvelteKit. В корне нашей папки routes мы можем создать +page.server.ts рядом с существующим +page.server.ts:
import type { PageServerLoad } from './$types';
export const load = (async ({ cookies }) => {
const jwt = cookies.get('jwt');
return {
jwt
};
}) satisfies PageServerLoad;
Что это делает, так это получает файл cookie jwt, который мы установили в перенаправлении, и передает его всем страницам на том же уровне routes или ниже.
Ранее, в нашем корне +page.svelte, вы могли заметить, что в нашем скрипте была дополнительная переменная:
export let data: PageData;
Эти данные заполняются тем, что возвращает функция load нашей страницы, в данном случае содержимым нашего файла cookie jwt. Мы хотим передать этот файл cookie в наш раздел PasskeyDemo:
<PasskeyDemo {data} />
В этом разделе нам также нужно объявить свойство data, чтобы получать его с родительской страницы. Это должно быть в нашем разделе скриптов:
export let data: PageData;
Теперь мы можем использовать это для условной визуализации нашего пользовательского интерфейса:
<!--- other code --->
{#if data && data.jwt}
<Card class="w-full">
<Heading tag="h4">That’s it. You’re logged in.</Heading>
<button href="/api/logout" pill class="bg-primary text-white mt-32 mb-8">Log out</button>
</Card>
{:else}
<Card class="w-full">
<Corbado-auth
style="border: none"
project_id="{PUBLIC_CORBADO_PROJECT_ID}"
conditional="yes"
login_title="Try passkey login"
login_btn="Passkey login"
register_title="Try passkey signup"
register_btn="Passkey signup"
page="register"
>
<input name="username" id="Corbado-username" value="" required autocomplete="webauthn" />
</Corbado-auth>
</Card>
{/if}
<!--- other code --->
Это отобразит либо наш веб-компонент, если мы не вошли в систему, либо кнопку выхода, если мы уже вошли в систему. Кнопка выхода использует другое действие. Мы можем создать это действие, просто создав файл api/logout/+server.ts со следующим содержимым:
import { redirect } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
export const GET = (({ cookies }) => {
cookies.set('jwt', '', {
path: '/',
expires: new Date(0)
});
throw redirect(303, '/');
}) satisfies RequestHandler;
Это действие будет вызвано при нажатии кнопки и удалит токен jwt из браузера и перенаправит обратно в корень страницы.
6. Заключение
Я надеюсь, что эта демонстрация показала, как легко быстро добавить аутентификацию без пароля с использованием ключей доступа в ваше приложение SvelteKit с помощью Corbado и использовать все функции SvelteKit, чтобы облегчить нашу жизнь в этом процессе.