Skip to content

Commit 5096101

Browse files
committed
Update auth
1 parent b091ab1 commit 5096101

File tree

5 files changed

+43
-29
lines changed

5 files changed

+43
-29
lines changed

docker-compose.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ services:
1111
MB_JWT_SHARED_SECRET: "${METABASE_JWT_SHARED_SECRET}"
1212
MB_SETUP_TOKEN: "${PREMIUM_EMBEDDING_TOKEN}"
1313
MB_PREMIUM_EMBEDDING_TOKEN: "${PREMIUM_EMBEDDING_TOKEN}"
14-
MB_JWT_IDENTITY_PROVIDER_URI: "http://localhost:${CLIENT_PORT_APP_ROUTER}/api/metabase/auth"
1514
healthcheck:
1615
test: curl --fail -X GET -I "http://localhost:${MB_PORT}/api/health" || exit 1
1716
interval: 15s

next-sample-app-router/src/app/api/metabase/auth/route.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import jwt from "jsonwebtoken";
2+
import { NextResponse } from 'next/server';
23

34
if (!process.env.METABASE_JWT_SHARED_SECRET) {
45
throw new Error("Missing METABASE_JWT_SHARED_SECRET");
@@ -10,7 +11,7 @@ if (!process.env.NEXT_PUBLIC_METABASE_INSTANCE_URL) {
1011
const METABASE_JWT_SHARED_SECRET = process.env.METABASE_JWT_SHARED_SECRET;
1112
const METABASE_INSTANCE_URL = process.env.METABASE_INSTANCE_URL;
1213

13-
export async function GET(req) {
14+
export async function GET(request: Request) {
1415
// this should come from the session
1516
const user = {
1617
@@ -30,8 +31,11 @@ export async function GET(req) {
3031
METABASE_JWT_SHARED_SECRET
3132
);
3233

33-
if (req.query.response === "json") {
34-
return new Response({ jwt: token });
34+
const url = new URL(request.url)
35+
const wantsJson = url.searchParams.get('response') === 'json'
36+
37+
if (wantsJson) {
38+
return NextResponse.json({ jwt: token })
3539
}
3640

3741
const ssoUrl = `${METABASE_INSTANCE_URL}/auth/sso?jwt=${token}`;

next-sample-app-router/src/app/app-provider.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ if (!process.env.NEXT_PUBLIC_METABASE_INSTANCE_URL) {
1313

1414
const authConfig = defineMetabaseAuthConfig({
1515
metabaseInstanceUrl: process.env.NEXT_PUBLIC_METABASE_INSTANCE_URL,
16+
fetchRequestToken: async () => {
17+
const response = await fetch('/api/metabase/auth?response=json', {
18+
method: "GET",
19+
credentials: "include",
20+
});
21+
22+
return await response.json();
23+
},
1624
});
1725

1826
const theme = defineMetabaseTheme({

next-sample-pages-router/src/components/app-provider.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ if (!process.env.NEXT_PUBLIC_METABASE_INSTANCE_URL) {
1111

1212
const authConfig = defineMetabaseAuthConfig({
1313
metabaseInstanceUrl: process.env.NEXT_PUBLIC_METABASE_INSTANCE_URL,
14+
fetchRequestToken: async () => {
15+
const response = await fetch('/api/metabase/auth?response=json', {
16+
method: "GET",
17+
credentials: "include",
18+
});
19+
20+
return await response.json();
21+
},
1422
});
1523

1624
const theme = defineMetabaseTheme({
Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,58 @@
1+
// pages/api/auth/sso.ts
2+
13
import type { NextApiRequest, NextApiResponse } from "next";
24
import jwt from "jsonwebtoken";
35

46
if (!process.env.METABASE_JWT_SHARED_SECRET) {
57
throw new Error("Missing METABASE_JWT_SHARED_SECRET");
68
}
7-
if (!process.env.NEXT_PUBLIC_METABASE_INSTANCE_URL) {
8-
throw new Error("Missing NEXT_PUBLIC_METABASE_INSTANCE_URL");
9+
if (!process.env.METABASE_INSTANCE_URL) {
10+
throw new Error("Missing METABASE_INSTANCE_URL");
911
}
1012

1113
const METABASE_JWT_SHARED_SECRET = process.env.METABASE_JWT_SHARED_SECRET;
1214
const METABASE_INSTANCE_URL = process.env.METABASE_INSTANCE_URL;
1315

14-
type MetabaseSession = {
15-
id: string;
16-
};
16+
type JsonResponse = { jwt: string };
1717

1818
export default async function handler(
1919
req: NextApiRequest,
20-
res: NextApiResponse<MetabaseSession>
20+
res: NextApiResponse<JsonResponse | string>
2121
) {
22-
// this should come from the session
22+
// In a real app you'd pull this from your session/cookie
2323
const user = {
2424
2525
firstName: "John",
2626
lastName: "Doe",
2727
group: "admin",
2828
};
2929

30+
// Sign a Metabase SSO JWT (10min expiration)
3031
const token = jwt.sign(
3132
{
3233
email: user.email,
3334
first_name: user.firstName,
3435
last_name: user.lastName,
3536
groups: [user.group],
36-
exp: Math.round(Date.now() / 1000) + 60 * 10, // 10 minutes expiration
37+
exp: Math.floor(Date.now() / 1000) + 60 * 10,
3738
},
38-
// This is the JWT signing secret in your Metabase JWT authentication setting
3939
METABASE_JWT_SHARED_SECRET
4040
);
4141

42+
// If ?response=json, return { jwt }
4243
if (req.query.response === "json") {
43-
res.write({ jwt: token });
44-
return res.end();
44+
return res.status(200).json({ jwt: token });
4545
}
46-
46+
// Otherwise proxy the SSO request to Metabase
4747
const ssoUrl = `${METABASE_INSTANCE_URL}/auth/sso?jwt=${token}`;
48+
4849
try {
49-
const response = await fetch(ssoUrl, { method: "GET" });
50-
const session = await response.text();
51-
52-
res.write(session);
53-
return res.end();
54-
} catch (error) {
55-
console.log("error", error);
56-
if (error instanceof Error) {
57-
res.write(error.message);
58-
return res.end();
59-
}
60-
res.write("unknown error");
61-
return res.end();
50+
const mbRes = await fetch(ssoUrl);
51+
const html = await mbRes.text();
52+
return res.status(mbRes.status).send(html);
53+
} catch (err) {
54+
console.error("Metabase SSO error:", err);
55+
const msg = err instanceof Error ? err.message : "Unknown error";
56+
return res.status(500).send(msg);
6257
}
6358
}

0 commit comments

Comments
 (0)