Aris
07/19/2022, 5:51 PMawait supabase.auth.signIn({email})
This triggers an email, and when the verification link is clicked, it redirects to http://localhost:5173/#access_token=[...]&expires_in=3600&refresh_token=[...]&token_type=bearer&type=magiclink
AFAIK that Supabase -> GoTrue -> redirect flow should set browser cookies, but that's not happening and I'm not sure whyNeedle
07/19/2022, 5:51 PMsilentworks
07/19/2022, 5:51 PMAris
07/19/2022, 5:56 PM<script lang="ts">
import {provider} from "$lib/auth"
async function submit() {
const email = "temporarily-hardcoded@example.com"
const res = await provider.signIn(
{email}
// temporarily removed
// {
// shouldCreateUser: true,
// redirectTo: "/auth/otp-ok",
// }
)
console.log("otp submit", res)
}
</script>
<form on:submit|preventDefault={submit}>
<div>
<input
type="email"
id="email"
name="email"
autocomplete="email"
placeholder="me@example.com"
required
/>
</div>
<button type="submit">Continue with email</button>
</form>Aris
07/19/2022, 5:57 PMimport {createClient} from "@supabase/supabase-js"
const supabase = createClient(
"https://....supabase.co",
"..."
)
export const provider = supabase.authsilentworks
07/19/2022, 6:22 PMAris
07/19/2022, 6:42 PM/ because Supabase doesn't seem to support custom redirects for Magic links. So I'm only doing logging to debug this:
// hooks.ts
export const handle: Handle = async ({event, resolve}) => {
const {
locals,
params,
request: {method, headers},
url: {pathname},
} = event
const cookies = cookie.parse(headers.get("cookie") ?? "")
console.log(`server: handle ${method} ${pathname}`, locals, params, cookies)
console.log(headers)
const res = await resolve(event)
return ressilentworks
07/19/2022, 6:43 PMsilentworks
07/19/2022, 6:44 PM@supabase/auth-helpers-sveltekit which handles this for you and also creates a cookie on your own domain?Aris
07/19/2022, 6:45 PMsilentworks
07/19/2022, 6:45 PMAris
07/19/2022, 6:46 PMAris
07/19/2022, 6:47 PMconst cookies = parseCookie(req.headers.get('cookie'));
This is what I'm trying to do as well.Aris
07/19/2022, 6:48 PM/callback endpoint, which is not applicable when using a Magic link?silentworks
07/19/2022, 6:48 PMsilentworks
07/19/2022, 6:48 PMsilentworks
07/19/2022, 6:49 PMsilentworks
07/19/2022, 6:50 PMsilentworks
07/19/2022, 6:52 PMhandleAuth hook https://github.com/silentworks/waiting-list/blob/archive/0.0.2/src/routes/__layout.svelte#L8-L21Aris
07/19/2022, 6:53 PMsilentworks
07/19/2022, 6:54 PMAris
07/19/2022, 6:54 PMrequest.json(), if Supabase is POSTing that on the redirect then I believe that's what I need to parsesilentworks
07/19/2022, 6:55 PMAris
07/19/2022, 6:56 PMconst expressStyleRequest = await toExpressRequest(request)
const { user } = await supabase.auth.api.getUserByCookie(expressStyleRequest)
export async function toExpressRequest(req, body = {}) {
return {
body,
headers: { host: req.headers.get('host') },
cookies: cookie.parse(req.headers.get('cookie') || '')
}
}silentworks
07/19/2022, 6:57 PMsilentworks
07/19/2022, 6:58 PM@supabase/auth-helpers-sveltekit and @supabase/auth-helpers-svelte libraries as they work with current SvelteKit.Aris
07/19/2022, 7:02 PMsilentworks
07/19/2022, 7:04 PMlocalhost)silentworks
07/19/2022, 7:04 PMsilentworks
07/19/2022, 7:06 PMhandleCallback is creating the cookie on your own domain (localhost)Aris
07/19/2022, 7:14 PMhandleCallback was passing through a cookie received from SB.
Here's the meat of `/handlecallBack`:
export const handleCallback = (options: HandleCallbackOptions = {}) => {
const handle: Handle = async ({ event, resolve }) => {
const req = event.request;
let res = await resolve(event);
[...]
const { event: bodyEvent, session } = await req.json();
if (bodyEvent === 'SIGNED_IN') {
if (!session) throw new Error('Auth session missing!');
setCookies(
new SvelteKitRequestAdapter(req),
new SvelteKitResponseAdapter(res),
[
session.access_token ? { key: 'access-token', value: session.access_token }: null,
]
)
}
}
}
The function grabs the session from req.json(). I'm not sure how this reconciles with your earlier remark that: "No Supabase isn't POSTing anything to the server." ?silentworks
07/19/2022, 7:18 PMAris
07/19/2022, 7:23 PM/
4) client /
5) client triggers registered auth listener state change
6) client listener fetches /callback (passing in session data somehow, hopefully I can find this in the supabase-js.auth code)
7) server /callback sets cookie for my domain as passed by above
8) client (still at /) refreshes auth state from /callback responsesilentworks
07/19/2022, 7:28 PMAris
07/19/2022, 7:45 PM__layout:load(), do if (browser) refreshAuth(url.hash), and put the machinery there (parse, set cookie/localStorage, clear hash, update Svelte $session store instead of firing event). Should eliminate the need for /callback and the application wrapper Svelte component AFAIC.silentworks
07/19/2022, 7:53 PMsupabase-js library, so you will have to catch it before the library catches it and removes it form the urlAris
07/19/2022, 7:54 PMsupabase-js a lot hardersilentworks
07/19/2022, 7:54 PMload is going away in SvelteKit at some point in the futureAris
07/19/2022, 7:55 PMAris
07/19/2022, 7:56 PMsilentworks
07/19/2022, 7:56 PMsilentworks
07/19/2022, 7:57 PMload would just be doing the work the onAuthStateChange is doing already for you.silentworks
07/19/2022, 7:58 PM$session store on the client doesn't persists the data for the next request. The ping/pong is there for that reason.silentworks
07/19/2022, 8:00 PMAris
07/19/2022, 8:02 PMAris
07/19/2022, 8:02 PMAris
07/19/2022, 8:02 PMAris
07/19/2022, 8:05 PMexport const {api, signIn, signOut} = supabase.auth
This broke with an error on this.removeSession() being undefined I believe, when I called signIn. Guessing the this reference is confused by the destructuring. It's minor, and I'm off the happy path already, so it didn't seem worth opening an issue.silentworks
07/19/2022, 8:16 PMauth-helpers, thats gotrue-js thingAris
07/19/2022, 9:36 PMif (settings.detectSessionInUrl && isBrowser() && !!getParameterByName('access_token')) {...}
This is in the client constructor, which supabase-js automatically instantiates for you. So, if you create a client instance somewhere on the browser side like __layout:onMount, it will process /#access_token=..., saving it to localStorage (no cookie set) under supabase.auth.tokenAris
07/19/2022, 9:39 PM// $lib/auth.ts
const supabase = createClient(
"https://....supabase.co",
"..."
)
export const provider = supabase.auth
// routes/__layout.svelte
<script lang="ts">
import {provider} from "$lib/auth"
</script>
Hopefully this helps the next person who searches Discordsilentworks
07/19/2022, 10:18 PM