Mobile support to come.
import "server-only";
import { createServerClient } from "@supabase/ssr";
import type { JwtPayload } from "@supabase/supabase-js";
import { PHASE_PRODUCTION_BUILD } from "next/constants";
import { cookies } from "next/headers";
import { type NextRequest, NextResponse } from "next/server";
/**
* we do *not* expose supabase environment variables in the client
* we use supabase in server functions *only* and in the middleware for auth.
*/
function getSupabaseConfig() {
const supabaseUrl = process.env.SUPABASE_URL;
const supabaseKey = process.env.SUPABASE_PUBLISHABLE_KEY;
if (!supabaseUrl || !supabaseKey) {
throw new Error("SUPABASE_URL and SUPABASE_PUBLISHABLE_KEY must be set");
}
return { supabaseUrl, supabaseKey };
}
/**
* this function should be called once per request
* as it is lightweight (just configures a fetch) and necessary (runs on serverless edge functions)
*/
export async function createSupabaseClient() {
const { supabaseUrl, supabaseKey } = getSupabaseConfig();
const cookieStore = await cookies();
return createServerClient(supabaseUrl, supabaseKey, {
cookies: {
getAll() {
return cookieStore.getAll();
},
setAll(cookiesToSet) {
try {
cookiesToSet.forEach(({ name, value, options }) => {
cookieStore.set(name, value, { ...options, httpOnly: true });
});
} catch (error) {
console.error(error);
}
},
},
});
}
/**
* invoked in middleware, checks for session and also updates session if expired
*/
export async function updateSession(request: NextRequest) {
const { supabaseUrl, supabaseKey } = getSupabaseConfig();
let supabaseResponse = NextResponse.next({ request });
const supabase = createServerClient(supabaseUrl, supabaseKey, {
cookies: {
getAll() {
return request.cookies.getAll();
},
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value }) => {
request.cookies.set(name, value);
});
supabaseResponse = NextResponse.next({
request,
});
cookiesToSet.forEach(({ name, value, options }) => {
supabaseResponse.cookies.set(name, value, options);
});
},
},
});
// checks session & refreshes if necessary, setting both cookies & supabaseResponse
const { data } = await supabase.auth.getClaims();
const user = data?.claims;
const pathname = request.nextUrl.pathname;
if (user && (pathname === "/login" || pathname === "/signup")) {
return NextResponse.redirect(new URL("/home", request.nextUrl));
} else if (!user && pathname === "/oauth/device") {
return NextResponse.redirect(
new URL("/login?redirect=/oauth/device", request.nextUrl),
);
}
// return the supabaseResponse object as-is, this is required to ensure that cookies are in sync between the server and client.
return supabaseResponse;
}
/**
* for use in server-components that need user identity info
*/
export async function getClaims(): Promise<JwtPayload | null> {
const supabase = await createSupabaseClient();
const { data } = await supabase.auth.getClaims();
return data?.claims || null;
}
/**
* for use when the full session (including access token) is needed
*/
export async function getSession() {
if (process.env.NEXT_PHASE === PHASE_PRODUCTION_BUILD) {
// constructing the supabase client awaits cookies, which causes failures if done at build time
// any page generated in buidl time is unauthenticated (e.g., public), so return null
return null;
}
const supabase = await createSupabaseClient();
const { data } = await supabase.auth.getSession();
return data.session;
}
refactoring to head -> /user/{username} for username existence checks
baepaul•2aaa7a42d ago
a lot of footguns eh
baepaul•17974422d ago
explaining my sins
baepaul•28edd616d ago
doing something risky and ill-advised :)
baepaul•b8881596d ago
styling login form + re organizing auth paths
baepaul•b49ac0c8d ago
getting rid of middleware auth checks for now and fixing cdp well-known
requesting urls it shouldn't be
baepaul•913a4d110d ago
inching towards public use
baepaul•ffa992610d ago
included auth token to api request
mike•a04fe2c22d ago
wiring up file viewer
baepaul•c9556f11mo ago
creating dal + dto, wiring up file-viewer GET request with static file
baepaul•76794a61mo ago
pulling in front-end code
baepaul•7c005641mo ago