Supabase has not too long ago introduced the revamped auth helpers for Supabase with SvelteKit help.
What are Auth Helpers?
In keeping with Supabase one of many challenges has been making a easy expertise for server-side rendering (SSR) environments. Auth Helpers are a group of framework-specific utilities for Supabase Auth. They let you implement safe functions with little effort. These libraries embrace features for shielding API routes and pages in your functions.
How you can use Supabase Auth Helpers in SvelteKit Projet?
TL;DR
Simply set up these two npm packages:
npm set up @supabase/auth-helpers-sveltekit
npm set up @supabase/auth-helpers-svelte
Detailed Tutorial
Set Up SvelteKit Mission
We are going to attempt to have a minimal naked bone mission. You might be free so as to add any styling,sort checking and many others later. Supabase has fairly good examples utilizing TypeScript out there right here.
Let identify the mission SvelteKitSupabaseAuthApp.
Simply use the Skeleton mission, no TypeScript, no ESLint, no Prettier, no Playwright.
npm create svelte@newest SvelteKitSupabaseAuthApp
cd SvelteKitSupabaseAuthApp
npm set up
Set up Supabase Auth Helpers for SvelteKit
npm set up @supabase/auth-helpers-sveltekit
npm set up @supabase/auth-helpers-svelte
Set Up Supabase Mission
- Login in Supabase and create a brand new mission on the Supabase dashboard.
- Go to Authentication > Settings part and alter Person Periods – Website URL from http://localhost:3000 to http://localhost:3000/5173 and save. This can be a localhost deal with the place SvelteKit serves the mission in developer mode. This transformation was launched with Vite 3.
- Go to Settings > API part and get the URL and anon key of your mission.
- Return to your SvelteKitSupabaseAuthApp mission and in its root create a brand new .env file. Exchange VITE_SUPABASE_URL with the URL from earlier step and VITE_SUPABASE_ANON_KEY with anon key from earlier step:
# .env
# Replace these with your Supabase particulars from your mission settings > API
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key
Supabase Consumer Creation
In src folder create a brand new folder lib and on this lib folder create a brand new file sb.js, right here we create supabaseClient utilizing our credentials from .env finish export the supabaseClient so we will use its auth strategies in our utility.
We are going to use login with e mail on this app. Supabase sends affirmation e mail mechanically when a person indicators ups.
// lib/sb,js
import { createSupabaseClient } from '@supabase/auth-helpers-sveltekit';
const { supabaseClient } = createSupabaseClient(
import.meta.env.VITE_SUPABASE_URL,
import.meta.env.VITE_SUPABASE_ANON_KEY
);
export { supabaseClient };
Hooks
In SvelteKit hook permits us to make use of two essential features, a deal with operate and a getSession operate. The deal with operate runs each time the SvelteKit server receives a request. The getSession operate takes the occasion object and returns a session object that’s accessible on the consumer, so we will for instance entry knowledge regarding person and cookies.
In src folder create a brand new file hooks.js
// src/hooks.js
import { handleAuth } from '@supabase/auth-helpers-sveltekit';
import { sequence } from '@sveltejs/equipment/hooks';
export const deal with = sequence(
...handleAuth({
cookieOptions: { lifetime: 1 * 365 * 24 * 60 * 60 }
})
);
export const getSession = async (occasion) => {
const { person, accessToken } = occasion.locals;
return {
person,
accessToken
};
};
Structure
In src/routes/ folder create a brand new format file __layout.svelte so we can’t solely have a easy format however extra importantly introduce our SupaAuthHelper element.
// src/routes/__layout.svelte
<script>
import { session } from '$app/shops';
import { supabaseClient } from '$lib/sb';
import { SupaAuthHelper } from '@supabase/auth-helpers-svelte';
</script>
<svelte:head>
<title>Electronic mail and Password Demo - Supabase Auth Helpers</title>
</svelte:head>
<SupaAuthHelper {supabaseClient} {session}>
<essential>
<div>
<h2>
<a href="/">Supabase Auth Helpers Demo</a>
</h2>
<slot />
<div>
{#if $session?.person?.id}
<a href="/api/auth/logout">Signal out</a>
{/if}
</div>
</div>
</essential>
</SupaAuthHelper>
Enroll Web page and Route
In src/routes/ folder create a brand new file signup,svelte Only a easy sing up type.
// src/routes/signup,svelte
<script>
export let errors = null;
export let values = null;
export let message = null;
</script>
<part>
<div>
<h1>Signal up</h1>
{#if errors}
<div>{errors.type}</div>
{/if}
{#if message}
<div>{message}</div>
{/if}
<type technique="put up">
<div>
<label for="e mail">Electronic mail</label>
<p>
<enter
id="e mail"
identify="e mail"
worth={values?.e mail ?? ''}
sort="e mail"
placeholder="Electronic mail"
required
/>
</p>
</div>
<div>
<label for="password">Password</label>
<p>
<enter
id="password"
identify="password"
worth={values?.password ?? ''}
sort="password"
placeholder="Password"
required
/>
</p>
</div>
<div>
<p>
<button>Signal up</button>
</p>
</div>
</type>
<div>
<p>
Already have an account? <a href="/">Signal in</a>
</p>
</div>
</div>
</part>
In src/routes/ folder create a brand new signup.js file. This endpoint factors present person to /dashboard which is protected person solely web page or supplies sing up knowledge to supabaseClient. We’re additionally including object specifying redirect when consumer clicks affirmation hyperlink in a affirmation e mail that Supabase will ship him/her.
// src/routes/signup.js
import { supabaseClient } from '$lib/sb';
export const GET = async ({ locals }) => {
// if the person is already logged in, then redirect to the dashboard
if (locals.person) {
return {
standing: 303,
headers: {
location: '/dashboard'
}
};
}
return {
standing: 200
};
};
export const POST = async ({ request, url }) => {
const knowledge = await request.formData();
const e mail = knowledge.get('e mail');
const password = knowledge.get('password');
const errors = {};
const values = { e mail, password };
const { error } = await supabaseClient.auth.signUp(
{ e mail, password },
{ redirectTo: `${url.origin}/logging-in`}
);
if (error) {
errors.type = error.message;
return {
standing: 400,
physique: {
errors,
values
}
};
}
return {
standing: 200,
physique: {
message: 'Please examine your e mail for a affirmation e mail.'
}
};
};
Log in (index) Web page and Route
In src/routes/ folder change index.svelte with this new one.Only a easy login type.
// src/routes/index.svelte
<script>
export let errors;
export let values;
</script>
<part>
<div>
<h1>Signal in</h1>
{#if errors}
<div>{errors.type}</div>
{/if}
<type technique="put up">
<div>
<label for="e mail">Electronic mail</label>
<p>
<enter
id="e mail"
identify="e mail"
worth={values?.e mail ?? ''}
sort="e mail"
placeholder="Electronic mail"
required
/>
</p>
</div>
<div>
<label for="password">Password</label>
<p>
<enter
id="password"
identify="password"
worth={values?.password ?? ''}
sort="password"
placeholder="Password"
required
/>
</p>
</div>
<div>
<p>
<button>Signal in</button>
</p>
</div>
</type>
<div>
<p>
Don't have an account? <a href="https://dev.to/signup">Enroll</a>
</p>
</div>
</div>
</part>
In src/routes/ folder create a brand new index.js file. This endpoint factors present person to /dashboard which is protected person solely web page or supplies login knowledge to supabaseClient, returned session is use for a cookie creation.
//src/routes/index.js
import { supabaseClient } from '$lib/sb';
export const GET = async ({ locals }) => {
if (locals.person) {
return {
standing: 303,
headers: {
location: '/dashboard'
}
};
}
return {
standing: 200
};
};
export const POST = async ({ request, url }) => {
const knowledge = await request.formData();
const e mail = knowledge.get('e mail');
const password = knowledge.get('password');
const headers = { location: '/dashboard' };
const errors = {};
const values = { e mail, password };
const { session, error } = await supabaseClient.auth.signIn({ e mail, password });
if (error) {
errors.type = error.message;
return {
standing: 400,
physique: {
errors,
values
}
};
}
if (session) {
const response = await fetch(`${url.origin}/api/auth/callback`, {
technique: 'POST',
headers: new Headers({ 'Content material-Sort': 'utility/json' }),
credentials: 'same-origin',
physique: JSON.stringify({ occasion: 'SIGNED_IN', session })
});
// TODO: Add helper inside auth-helpers-sveltekit library to handle this higher
const cookies = response.headers
.get('set-cookie')
.break up('SameSite=Lax, ')
.map((cookie) => {
if (!cookie.contains('SameSite=Lax')) {
cookie += 'SameSite=Lax';
}
return cookie;
});
headers['Set-Cookie'] = cookies;
}
return {
standing: 303,
headers
};
};
Electronic mail affirmation redirect web page
In src/routes/ folder create a brand new file logging-in@clean.svelte so we will examine if the person redirected after e mail affirmation has been already set in session retailer. We can even present a particular format for this case in a while. Throughout my exams the redirect and session retailer had been fairly quick so this web page could also be seen slightly hardly ever.
src/routes/logging-in@clean.svelte
<script>
import { session } from '$app/shops';
import { goto } from '$app/navigation';
import { web page } from '$app/shops';
let redirectPath = '/dashboard';
$: {
const redirectTo = $web page.url.searchParams.get('redirect');
if (redirectTo) {
redirectPath = redirectTo;
}
// examine if person has been set in session retailer then redirect
if ($session?.person?.id) {
goto(redirectPath);
}
}
</script>
<part>
<div>
<progress class="progress" max="100" />
</div>
<div>
Signing in from the e mail affirmation hyperlink ...
</div>
</part>
<type>
.progress:indeterminate {
animation-period: 3.8s;
}
</type>
Dashboard Web page and Route – protected customers solely web page
In src/routes/ folder create a brand new file dashboard.svelte the place we show some knowledge about person saved by Supabase,
src/routes/dashboard.svelte
<script>
export let person;
</script>
<div>
<h3>This is protected route accesible solely for ligged customers</h3>
<p>Hiya person {person.e mail}</p>
</div>
<div>
<p>Person {person.e mail} particulars:</p>
<pre>{JSON.stringify(person, null, 2)}</pre>
</div>
In src/routes/ folder create a brand new dashboard.js file.
src/routes/dashboard.js
import { supabaseServerClient, withApiAuth } from '@supabase/auth-helpers-sveltekit';
export const GET = async ({ locals, request }) =>
withApiAuth(
{
redirectTo: '/',
person: locals.person
},
async () => {
// const { knowledge } = await supabaseServerClient(request).from('take a look at').choose('*');
return {
physique: {
// knowledge,
person: locals.person
}
};
}
);
Electronic mail Affirmation Redirect Structure
In src/routes/ folder create a brand new file __layout-blank.svelte the place we’re having a particular named format for e mail affirmation redirect as talked about earlier.
//src/routes/__layout-blank.svelte
<script>
import { session } from '$app/shops';
import { supabaseClient } from '$lib/sb';
import { SupaAuthHelper } from '@supabase/auth-helpers-svelte';
</script>
<svelte:head>
<title>Electronic mail and Password Demo - Supabase Auth Helpers</title>
</svelte:head>
<SupaAuthHelper {supabaseClient} {session}>
<slot />
</SupaAuthHelper>
I hope this tutorial was helpful. Large thank to Supabase guys for SvelteKit Auth Helpers, their examples the place true supply for this text. As a result of I’m actually no auth skilled especial y regarding SSR all feedback, corrections or enhancements are welcomed.