Skip to content

Commit d511dbe

Browse files
committed
eng-1762: Rewrite token logic as server-side route
1 parent c8e0c4a commit d511dbe

6 files changed

Lines changed: 155 additions & 127 deletions

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {
2+
Card,
3+
CardContent,
4+
CardHeader,
5+
CardTitle,
6+
} from "@repo/ui/components/ui/card";
7+
8+
const Page = async ({
9+
searchParams,
10+
}: {
11+
searchParams: Promise<{ error: string }>;
12+
}) => {
13+
const params = await searchParams;
14+
15+
return (
16+
<div className="flex min-h-svh w-full items-center justify-center p-6 md:p-10">
17+
<div className="w-full max-w-sm">
18+
<div className="flex flex-col gap-6">
19+
<Card>
20+
<CardHeader>
21+
<CardTitle className="text-2xl">
22+
Sorry, something went wrong.
23+
</CardTitle>
24+
</CardHeader>
25+
<CardContent>
26+
{params?.error ? (
27+
<p className="text-muted-foreground text-sm">
28+
Code error: {params.error}
29+
</p>
30+
) : (
31+
<p className="text-muted-foreground text-sm">
32+
An unspecified error occurred.
33+
</p>
34+
)}
35+
</CardContent>
36+
</Card>
37+
</div>
38+
</div>
39+
</div>
40+
);
41+
};
42+
43+
export default Page;

apps/website/app/(home)/auth/token/page.tsx

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { NextRequest, NextResponse } from "next/server";
2+
import { createClient } from "~/utils/supabase/server";
3+
import internalError from "~/utils/internalErrorSsr";
4+
5+
export const GET = async (request: NextRequest): Promise<NextResponse> => {
6+
const params = request.nextUrl.searchParams;
7+
const token = params.get("t");
8+
const url = params.get("url");
9+
try {
10+
if (typeof token !== "string") throw new Error("Please provide a token");
11+
if (typeof url !== "string") throw new Error("Please provide a single URL");
12+
13+
const client = await createClient();
14+
const result = await client.rpc("get_secret_token", {
15+
token,
16+
});
17+
if (result.error) {
18+
internalError({ error: result.error, type: "get-secret-token" });
19+
throw new Error("Could not connect to DiscourseGraphs");
20+
}
21+
if (result.data == null) {
22+
internalError({ error: "missing token", type: "get-secret-token" });
23+
throw new Error("Could not retrieve information, please try again.");
24+
}
25+
if (typeof result.data !== "string") {
26+
internalError({
27+
error: "payload-not-string",
28+
type: "get-secret-token",
29+
});
30+
throw new Error(
31+
"DiscourseGraphs configuration error, the team has been warned",
32+
);
33+
}
34+
const data = JSON.parse(result.data) as {
35+
/* eslint-disable @typescript-eslint/naming-convention */
36+
access_token: string;
37+
refresh_token: string;
38+
/* eslint-enable @typescript-eslint/naming-convention */
39+
};
40+
if (
41+
!data ||
42+
typeof data !== "object" ||
43+
!data.access_token ||
44+
!data.refresh_token
45+
) {
46+
internalError({ error: "misshaped-payload", type: "get-secret-token" });
47+
throw new Error(
48+
"DiscourseGraphs configuration error, the team has been warned",
49+
);
50+
}
51+
const response = await client.auth.setSession(data);
52+
if (response.error) {
53+
throw response.error;
54+
}
55+
} catch (error) {
56+
return NextResponse.redirect(
57+
new URL(
58+
"/auth/error?error=" +
59+
encodeURIComponent(
60+
error instanceof Error
61+
? error.message
62+
: "Unkown error while logging you in.",
63+
),
64+
request.nextUrl,
65+
),
66+
);
67+
}
68+
return NextResponse.redirect(
69+
new URL(url, url.startsWith("http") ? undefined : request.nextUrl),
70+
);
71+
};

apps/website/app/components/auth/LoginWithToken.tsx

Lines changed: 0 additions & 97 deletions
This file was deleted.

apps/website/app/utils/supabase/middleware.ts renamed to apps/website/app/utils/supabase/proxy.ts

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,24 @@ import { NextResponse, type NextRequest } from "next/server";
33
import { envContents } from "@repo/database/dbDotEnv";
44

55
// This would allow to create Next pages gated by a login middleware,
6-
// as described here: https://nextjs.org/docs/app/api-reference/file-conventions/middleware
7-
// Not usable yet, waiting for ENG-373
8-
// Inspired by https://supabase.com/ui/docs/nextjs/password-based-auth
6+
// as described here: https://supabase.com/docs/guides/auth/server-side/creating-a-client
97

108
export const updateSession = async (request: NextRequest) => {
9+
let supabaseResponse = NextResponse.next({
10+
request,
11+
});
1112
const dbEnv = envContents();
1213
const supabaseUrl = dbEnv.SUPABASE_URL;
1314
const supabaseKey = dbEnv.SUPABASE_PUBLISHABLE_KEY;
15+
if (supabaseUrl === undefined || supabaseKey === undefined)
16+
throw new Error("Configuration error: supabase variables not configured.");
1417

15-
if (!supabaseUrl || !supabaseKey) {
16-
throw new Error("Missing required Supabase environment variables");
17-
}
18-
19-
let supabaseResponse = NextResponse.next({ request });
20-
18+
// With Fluid compute, don't put this client in a global environment
19+
// variable. Always create a new one on each request.
2120
const supabase = createServerClient(supabaseUrl, supabaseKey, {
2221
cookies: {
2322
getAll: () => request.cookies.getAll(),
24-
setAll: (cookiesToSet) => {
23+
setAll: (cookiesToSet, headers) => {
2524
cookiesToSet.forEach(({ name, value }) =>
2625
request.cookies.set(name, value),
2726
);
@@ -31,33 +30,39 @@ export const updateSession = async (request: NextRequest) => {
3130
cookiesToSet.forEach(({ name, value, options }) =>
3231
supabaseResponse.cookies.set(name, value, options),
3332
);
33+
Object.entries(headers).forEach(([key, value]) =>
34+
supabaseResponse.headers.set(key, value),
35+
);
3436
},
3537
},
3638
});
3739

3840
// Do not run code between createServerClient and
39-
// supabase.auth.getUser(). A simple mistake could make it very hard to debug
41+
// supabase.auth.getClaims(). A simple mistake could make it very hard to debug
4042
// issues with users being randomly logged out.
4143

42-
// IMPORTANT: DO NOT REMOVE auth.getUser()
44+
// IMPORTANT: If you remove getClaims() and you use server-side rendering
45+
// with the Supabase client, your users may be randomly logged out.
46+
47+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
48+
const { data } = await supabase.auth.getClaims();
4349

44-
const {
45-
data: { user },
46-
} = await supabase.auth.getUser();
50+
/* Wait on this until we have login
51+
const user = data?.claims;
4752
4853
if (
4954
!user &&
50-
!request.nextUrl.pathname.startsWith("/login") &&
5155
!request.nextUrl.pathname.startsWith("/auth")
5256
) {
5357
// no user, potentially respond by redirecting the user to the login page
5458
const url = request.nextUrl.clone();
5559
url.pathname = "/auth/login";
5660
return NextResponse.redirect(url);
5761
}
62+
*/
5863

59-
// IMPORTANT: You *must* return the supabaseResponse object as it is.
60-
// If you're creating a new response object with NextResponse.next() make sure to:
64+
// IMPORTANT: You *must* return the supabaseResponse object as it is. If you're
65+
// creating a new response object with NextResponse.next() make sure to:
6166
// 1. Pass the request in it, like so:
6267
// const myNewResponse = NextResponse.next({ request })
6368
// 2. Copy over the cookies, like so:

apps/website/proxy.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { type NextRequest } from "next/server";
2+
import { updateSession } from "~/utils/supabase/proxy";
3+
4+
export const proxy = async (request: NextRequest) =>
5+
await updateSession(request);
6+
7+
export const config = {
8+
matcher: [
9+
/*
10+
* Match all request paths except for the ones starting with:
11+
* - _next/static (static files)
12+
* - _next/image (image optimization files)
13+
* - favicon.ico (favicon file)
14+
* Feel free to modify this pattern to include more paths.
15+
*/
16+
"/((?!_next/static|_next/image|favicon.ico|docs|blog|nextra|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
17+
],
18+
};

0 commit comments

Comments
 (0)