@propelauth/nextjs 0.0.97 → 0.0.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/app-router/index.js +77 -35
- package/dist/server/app-router/index.js.map +1 -1
- package/dist/server/app-router/index.mjs +77 -35
- package/dist/server/app-router/index.mjs.map +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/pages/index.d.ts +1 -1
- package/dist/server/pages/index.js +3 -3
- package/dist/server/pages/index.js.map +1 -1
- package/dist/server/pages/index.mjs +3 -3
- package/dist/server/pages/index.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -294,7 +294,7 @@ function refreshTokenWithAccessAndRefreshToken(refreshToken) {
|
|
|
294
294
|
accessToken,
|
|
295
295
|
error: "none"
|
|
296
296
|
};
|
|
297
|
-
} else if (response.status === 400) {
|
|
297
|
+
} else if (response.status === 400 || response.status === 401) {
|
|
298
298
|
return { error: "unauthorized" };
|
|
299
299
|
} else {
|
|
300
300
|
return { error: "unexpected" };
|
|
@@ -385,33 +385,11 @@ function authMiddleware(req) {
|
|
|
385
385
|
var _a, _b;
|
|
386
386
|
if (req.headers.has(CUSTOM_HEADER_FOR_ACCESS_TOKEN)) {
|
|
387
387
|
throw new Error(`${CUSTOM_HEADER_FOR_ACCESS_TOKEN} is set which is for internal use only`);
|
|
388
|
-
} else if (req.nextUrl.pathname === CALLBACK_PATH || req.nextUrl.pathname === LOGOUT_PATH) {
|
|
388
|
+
} else if (req.nextUrl.pathname === CALLBACK_PATH || req.nextUrl.pathname === LOGOUT_PATH || req.nextUrl.pathname === USERINFO_PATH) {
|
|
389
389
|
return import_server.NextResponse.next();
|
|
390
390
|
}
|
|
391
391
|
const accessToken = (_a = req.cookies.get(ACCESS_TOKEN_COOKIE_NAME)) == null ? void 0 : _a.value;
|
|
392
392
|
const refreshToken = (_b = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)) == null ? void 0 : _b.value;
|
|
393
|
-
if (req.nextUrl.pathname === USERINFO_PATH && refreshToken) {
|
|
394
|
-
const response = yield refreshTokenWithAccessAndRefreshToken(refreshToken);
|
|
395
|
-
if (response.error === "unexpected") {
|
|
396
|
-
throw new Error("Unexpected error while refreshing access token");
|
|
397
|
-
} else if (response.error === "unauthorized") {
|
|
398
|
-
const headers2 = new Headers();
|
|
399
|
-
headers2.append("Set-Cookie", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
400
|
-
headers2.append("Set-Cookie", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
401
|
-
return new Response("Unauthorized", { status: 401, headers: headers2 });
|
|
402
|
-
} else {
|
|
403
|
-
const headers2 = new Headers(req.headers);
|
|
404
|
-
headers2.append(CUSTOM_HEADER_FOR_ACCESS_TOKEN, response.accessToken);
|
|
405
|
-
const nextResponse = import_server.NextResponse.next({
|
|
406
|
-
request: {
|
|
407
|
-
headers: headers2
|
|
408
|
-
}
|
|
409
|
-
});
|
|
410
|
-
nextResponse.cookies.set(ACCESS_TOKEN_COOKIE_NAME, response.accessToken, COOKIE_OPTIONS);
|
|
411
|
-
nextResponse.cookies.set(REFRESH_TOKEN_COOKIE_NAME, response.refreshToken, COOKIE_OPTIONS);
|
|
412
|
-
return nextResponse;
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
393
|
if (accessToken) {
|
|
416
394
|
const user = yield validateAccessTokenOrUndefined(accessToken);
|
|
417
395
|
if (user) {
|
|
@@ -474,14 +452,12 @@ function getRouteHandlers(args) {
|
|
|
474
452
|
var _a;
|
|
475
453
|
const oauthState = (_a = req.cookies.get(STATE_COOKIE_NAME)) == null ? void 0 : _a.value;
|
|
476
454
|
if (!oauthState || oauthState.length !== 64) {
|
|
477
|
-
console.log("No oauth state found");
|
|
478
455
|
return new Response(null, { status: 302, headers: { Location: LOGIN_PATH } });
|
|
479
456
|
}
|
|
480
457
|
const queryParams = req.nextUrl.searchParams;
|
|
481
458
|
const state = queryParams.get("state");
|
|
482
459
|
const code = queryParams.get("code");
|
|
483
460
|
if (state !== oauthState) {
|
|
484
|
-
console.log("Mismatch between states, redirecting to login");
|
|
485
461
|
return new Response(null, { status: 302, headers: { Location: LOGIN_PATH } });
|
|
486
462
|
}
|
|
487
463
|
const oauth_token_body = {
|
|
@@ -523,8 +499,19 @@ function getRouteHandlers(args) {
|
|
|
523
499
|
function userinfoGetHandler(req) {
|
|
524
500
|
return __async(this, null, function* () {
|
|
525
501
|
var _a;
|
|
526
|
-
const
|
|
527
|
-
if (
|
|
502
|
+
const oldRefreshToken = (_a = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)) == null ? void 0 : _a.value;
|
|
503
|
+
if (oldRefreshToken) {
|
|
504
|
+
const refreshResponse = yield refreshTokenWithAccessAndRefreshToken(oldRefreshToken);
|
|
505
|
+
if (refreshResponse.error === "unexpected") {
|
|
506
|
+
throw new Error("Unexpected error while refreshing access token");
|
|
507
|
+
} else if (refreshResponse.error === "unauthorized") {
|
|
508
|
+
const headers3 = new Headers();
|
|
509
|
+
headers3.append("Set-Cookie", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
510
|
+
headers3.append("Set-Cookie", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
511
|
+
return new Response("Unauthorized", { status: 401, headers: headers3 });
|
|
512
|
+
}
|
|
513
|
+
const refreshToken = refreshResponse.refreshToken;
|
|
514
|
+
const accessToken = refreshResponse.accessToken;
|
|
528
515
|
const path = `${authUrlOrigin}/propelauth/oauth/userinfo`;
|
|
529
516
|
const response = yield fetch(path, {
|
|
530
517
|
headers: {
|
|
@@ -540,32 +527,85 @@ function getRouteHandlers(args) {
|
|
|
540
527
|
accessToken,
|
|
541
528
|
impersonatorUserId: userFromToken.impersonatorUserId
|
|
542
529
|
};
|
|
530
|
+
const headers3 = new Headers();
|
|
531
|
+
headers3.append("Set-Cookie", `${ACCESS_TOKEN_COOKIE_NAME}=${accessToken}; Path=/; HttpOnly; Secure; SameSite=Lax`);
|
|
532
|
+
headers3.append("Set-Cookie", `${REFRESH_TOKEN_COOKIE_NAME}=${refreshToken}; Path=/; HttpOnly; Secure; SameSite=Lax`);
|
|
533
|
+
headers3.append("Content-Type", "application/json");
|
|
543
534
|
return new Response(JSON.stringify(jsonResponse), {
|
|
544
535
|
status: 200,
|
|
545
|
-
headers:
|
|
546
|
-
"Content-Type": "application/json"
|
|
547
|
-
}
|
|
536
|
+
headers: headers3
|
|
548
537
|
});
|
|
549
538
|
} else if (response.status === 401) {
|
|
550
|
-
|
|
539
|
+
const headers3 = new Headers();
|
|
540
|
+
headers3.append("Set-Cookie", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
541
|
+
headers3.append("Set-Cookie", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
542
|
+
return new Response(null, {
|
|
543
|
+
status: 401,
|
|
544
|
+
headers: headers3
|
|
545
|
+
});
|
|
551
546
|
} else {
|
|
552
547
|
return new Response(null, { status: 500 });
|
|
553
548
|
}
|
|
554
549
|
}
|
|
550
|
+
const headers2 = new Headers();
|
|
551
|
+
headers2.append("Set-Cookie", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
552
|
+
headers2.append("Set-Cookie", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
555
553
|
return new Response(null, { status: 401 });
|
|
556
554
|
});
|
|
557
555
|
}
|
|
556
|
+
function logoutGetHandler(req) {
|
|
557
|
+
return __async(this, null, function* () {
|
|
558
|
+
var _a;
|
|
559
|
+
const path = (args == null ? void 0 : args.postLoginRedirectPathFn) ? args.postLoginRedirectPathFn(req) : "/";
|
|
560
|
+
if (!path) {
|
|
561
|
+
console.log("postLoginPathFn returned undefined");
|
|
562
|
+
return new Response("Unexpected error", { status: 500 });
|
|
563
|
+
}
|
|
564
|
+
const refreshToken = (_a = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)) == null ? void 0 : _a.value;
|
|
565
|
+
if (!refreshToken) {
|
|
566
|
+
const headers2 = new Headers();
|
|
567
|
+
headers2.append("Location", path);
|
|
568
|
+
headers2.append("Set-Cookie", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
569
|
+
headers2.append("Set-Cookie", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
570
|
+
return new Response(null, {
|
|
571
|
+
status: 302,
|
|
572
|
+
headers: headers2
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
const refreshResponse = yield refreshTokenWithAccessAndRefreshToken(refreshToken);
|
|
576
|
+
if (refreshResponse.error === "unexpected") {
|
|
577
|
+
console.error("Unexpected error while refreshing access token");
|
|
578
|
+
return new Response("Unexpected error", { status: 500 });
|
|
579
|
+
} else if (refreshResponse.error === "unauthorized") {
|
|
580
|
+
const headers2 = new Headers();
|
|
581
|
+
headers2.append("Location", path);
|
|
582
|
+
headers2.append("Set-Cookie", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
583
|
+
headers2.append("Set-Cookie", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
584
|
+
return new Response(null, {
|
|
585
|
+
status: 302,
|
|
586
|
+
headers: headers2
|
|
587
|
+
});
|
|
588
|
+
} else {
|
|
589
|
+
const headers2 = new Headers();
|
|
590
|
+
headers2.append("Location", path);
|
|
591
|
+
return new Response(null, {
|
|
592
|
+
status: 302,
|
|
593
|
+
headers: headers2
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
});
|
|
597
|
+
}
|
|
558
598
|
function logoutPostHandler(req) {
|
|
559
599
|
return __async(this, null, function* () {
|
|
560
600
|
var _a;
|
|
561
|
-
const
|
|
562
|
-
if (!
|
|
601
|
+
const refreshToken = (_a = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)) == null ? void 0 : _a.value;
|
|
602
|
+
if (!refreshToken) {
|
|
563
603
|
const headers3 = new Headers();
|
|
564
604
|
headers3.append("Set-Cookie", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
565
605
|
headers3.append("Set-Cookie", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
566
606
|
return new Response(null, { status: 200, headers: headers3 });
|
|
567
607
|
}
|
|
568
|
-
const logoutBody = { refresh_token };
|
|
608
|
+
const logoutBody = { refresh_token: refreshToken };
|
|
569
609
|
const url = `${authUrlOrigin}/api/backend/v1/logout`;
|
|
570
610
|
const response = yield fetch(url, {
|
|
571
611
|
method: "POST",
|
|
@@ -597,6 +637,8 @@ function getRouteHandlers(args) {
|
|
|
597
637
|
return callbackGetHandler(req);
|
|
598
638
|
} else if (params.slug === "userinfo") {
|
|
599
639
|
return userinfoGetHandler(req);
|
|
640
|
+
} else if (params.slug === "logout") {
|
|
641
|
+
return logoutGetHandler(req);
|
|
600
642
|
} else {
|
|
601
643
|
return new Response("", { status: 404 });
|
|
602
644
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/app-router-index.ts","../../../src/server/exceptions.ts","../../../src/server/app-router.ts","../../../src/user.ts","../../../src/server/shared.ts"],"sourcesContent":["export {UnauthorizedException, ConfigurationException} from \"./exceptions\"\nexport {getRouteHandlers, getUser, getUserOrRedirect, getAccessToken, authMiddleware} from \"./app-router\"\nexport type {RouteHandlerArgs} from \"./app-router\"\n","export class UnauthorizedException extends Error {\n readonly message: string\n readonly status: number\n\n constructor(message: string) {\n super(message)\n this.message = message\n this.status = 401\n }\n}\n\nexport class ConfigurationException extends Error {\n readonly message: string\n readonly status: number\n\n constructor(message: string) {\n super(message)\n this.message = message\n this.status = 500\n }\n}\n","import {redirect} from \"next/navigation.js\";\nimport {cookies, headers} from \"next/headers.js\";\nimport {NextRequest, NextResponse} from \"next/server.js\";\nimport {\n ACCESS_TOKEN_COOKIE_NAME,\n CALLBACK_PATH,\n COOKIE_OPTIONS,\n CUSTOM_HEADER_FOR_ACCESS_TOKEN,\n getAuthUrlOrigin,\n getIntegrationApiKey,\n getRedirectUri,\n LOGIN_PATH,\n LOGOUT_PATH,\n REFRESH_TOKEN_COOKIE_NAME,\n refreshTokenWithAccessAndRefreshToken,\n STATE_COOKIE_NAME,\n USERINFO_PATH,\n validateAccessToken,\n validateAccessTokenOrUndefined\n} from \"./shared\";\nimport {UserFromToken} from \"./index\"\n\nexport async function getUserOrRedirect(): Promise<UserFromToken> {\n const user = await getUser()\n if (user) {\n return user\n } else {\n redirect(LOGIN_PATH)\n throw new Error(\"Redirecting to login\")\n }\n}\n\nexport async function getUser(): Promise<UserFromToken | undefined> {\n const accessToken = headers().get(CUSTOM_HEADER_FOR_ACCESS_TOKEN) || cookies().get(ACCESS_TOKEN_COOKIE_NAME)?.value\n if (accessToken) {\n const user = await validateAccessTokenOrUndefined(accessToken)\n if (user) {\n return user\n }\n }\n return undefined\n}\n\nexport async function getAccessToken(): Promise<string | undefined> {\n return headers().get(CUSTOM_HEADER_FOR_ACCESS_TOKEN) || cookies().get(ACCESS_TOKEN_COOKIE_NAME)?.value\n}\n\n// Purpose of this middleware is just to keep the access token cookie alive\n// In an ideal world, this could be done in `getUser`, however, you can't\n// set a cookie in a server component.\n// There also doesn't seem to be any way right now to set a cookie in a\n// middleware and pass it forward (you can only set them on the response).\n// You CAN, however, pass in custom headers,\n// so we'll use CUSTOM_HEADER_FOR_ACCESS_TOKEN as a workaround\nexport async function authMiddleware(req: NextRequest): Promise<Response> {\n if (req.headers.has(CUSTOM_HEADER_FOR_ACCESS_TOKEN)) {\n throw new Error(`${CUSTOM_HEADER_FOR_ACCESS_TOKEN} is set which is for internal use only`)\n } else if (req.nextUrl.pathname === CALLBACK_PATH || req.nextUrl.pathname === LOGOUT_PATH) {\n // Don't do anything for the callback or logout paths, as they will modify the cookies themselves\n return NextResponse.next()\n }\n\n const accessToken = req.cookies.get(ACCESS_TOKEN_COOKIE_NAME)?.value\n const refreshToken = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value\n\n // For the userinfo endpoint, we want to get the most up-to-date info, so we'll refresh the access token\n if (req.nextUrl.pathname === USERINFO_PATH && refreshToken) {\n const response = await refreshTokenWithAccessAndRefreshToken(refreshToken)\n if (response.error === \"unexpected\") {\n throw new Error(\"Unexpected error while refreshing access token\")\n } else if (response.error === \"unauthorized\") {\n const headers = new Headers()\n headers.append(\"Set-Cookie\", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n headers.append(\"Set-Cookie\", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n return new Response(\"Unauthorized\", {status: 401, headers})\n } else {\n const headers = new Headers(req.headers)\n // Pass along the new access token in a header since cookies don't work\n headers.append(CUSTOM_HEADER_FOR_ACCESS_TOKEN, response.accessToken)\n const nextResponse = NextResponse.next({\n request: {\n headers\n }\n })\n nextResponse.cookies.set(ACCESS_TOKEN_COOKIE_NAME, response.accessToken, COOKIE_OPTIONS)\n nextResponse.cookies.set(REFRESH_TOKEN_COOKIE_NAME, response.refreshToken, COOKIE_OPTIONS)\n return nextResponse\n }\n }\n\n // If we are authenticated, we can continue\n if (accessToken) {\n const user = await validateAccessTokenOrUndefined(accessToken)\n if (user) {\n return NextResponse.next()\n }\n }\n\n // Otherwise, we need to refresh the access token\n if (refreshToken) {\n const response = await refreshTokenWithAccessAndRefreshToken(refreshToken)\n if (response.error === \"unexpected\") {\n throw new Error(\"Unexpected error while refreshing access token\")\n } else if (response.error === \"unauthorized\") {\n const response = NextResponse.next()\n response.cookies.delete(ACCESS_TOKEN_COOKIE_NAME)\n response.cookies.delete(REFRESH_TOKEN_COOKIE_NAME)\n return response\n } else {\n const headers = new Headers(req.headers)\n // Pass along the new access token in a header since cookies don't work\n headers.append(CUSTOM_HEADER_FOR_ACCESS_TOKEN, response.accessToken)\n const nextResponse = NextResponse.next({\n request: {\n headers\n }\n })\n nextResponse.cookies.set(ACCESS_TOKEN_COOKIE_NAME, response.accessToken, COOKIE_OPTIONS)\n nextResponse.cookies.set(REFRESH_TOKEN_COOKIE_NAME, response.refreshToken, COOKIE_OPTIONS)\n return nextResponse\n }\n }\n\n return NextResponse.next()\n}\n\nexport type RouteHandlerArgs = {\n postLoginRedirectPathFn?: (req: NextRequest) => string\n}\n\nexport function getRouteHandlers(args?: RouteHandlerArgs) {\n const authUrlOrigin = getAuthUrlOrigin()\n const redirectUri = getRedirectUri()\n const integrationApiKey = getIntegrationApiKey()\n\n function loginGetHandler() {\n const state = randomState()\n const authorize_url =\n authUrlOrigin + \"/propelauth/ssr/authorize?redirect_uri=\" + redirectUri + \"&state=\" + state\n return new Response(null, {\n status: 302,\n headers: {\n Location: authorize_url,\n \"Set-Cookie\": `${STATE_COOKIE_NAME}=${state}; Path=/; HttpOnly; Secure; SameSite=Lax`,\n }\n })\n }\n\n function signupGetHandler() {\n const state = randomState()\n const authorize_url =\n getAuthUrlOrigin() + \"/propelauth/ssr/authorize?redirect_uri=\" + redirectUri + \"&state=\" + state + \"&signup=true\"\n return new Response(null, {\n status: 302,\n headers: {\n Location: authorize_url,\n \"Set-Cookie\": `${STATE_COOKIE_NAME}=${state}; Path=/; HttpOnly; Secure; SameSite=Lax`,\n }\n })\n }\n\n async function callbackGetHandler(req: NextRequest) {\n const oauthState = req.cookies.get(STATE_COOKIE_NAME)?.value\n if (!oauthState || oauthState.length !== 64) {\n console.log(\"No oauth state found\")\n return new Response(null, {status: 302, headers: {Location: LOGIN_PATH}})\n }\n\n const queryParams = req.nextUrl.searchParams\n const state = queryParams.get(\"state\")\n const code = queryParams.get(\"code\")\n if (state !== oauthState) {\n console.log(\"Mismatch between states, redirecting to login\")\n return new Response(null, {status: 302, headers: {Location: LOGIN_PATH}})\n }\n\n const oauth_token_body = {\n redirect_uri: redirectUri,\n code,\n }\n const url = `${authUrlOrigin}/propelauth/ssr/token`\n const response = await fetch(url, {\n method: \"POST\",\n body: JSON.stringify(oauth_token_body),\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: \"Bearer \" + integrationApiKey,\n },\n })\n\n if (response.ok) {\n const data = await response.json()\n\n const accessToken = data.access_token\n const path = args?.postLoginRedirectPathFn ? args.postLoginRedirectPathFn(req) : \"/\"\n if (!path) {\n console.log(\"postLoginPathFn returned undefined\")\n return new Response(\"Unexpected error\", {status: 500})\n }\n\n const headers = new Headers()\n headers.append(\"Location\", path)\n headers.append(\"Set-Cookie\", `${ACCESS_TOKEN_COOKIE_NAME}=${accessToken}; Path=/; HttpOnly; Secure; SameSite=Lax`)\n headers.append(\"Set-Cookie\", `${REFRESH_TOKEN_COOKIE_NAME}=${data.refresh_token}; Path=/; HttpOnly; Secure; SameSite=Lax`)\n return new Response(null, {\n status: 302,\n headers\n })\n } else if (response.status === 401) {\n return new Response(\"Unexpected error\", {status: 500})\n } else {\n return new Response(\"Unexpected error\", {status: 500})\n }\n }\n\n async function userinfoGetHandler(req: NextRequest) {\n const accessToken = req.headers.get(CUSTOM_HEADER_FOR_ACCESS_TOKEN) || req.cookies.get(ACCESS_TOKEN_COOKIE_NAME)?.value\n if (accessToken) {\n const path = `${authUrlOrigin}/propelauth/oauth/userinfo`\n const response = await fetch(path, {\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"Bearer \" + accessToken,\n }\n })\n if (response.ok) {\n const userFromToken = await validateAccessToken(accessToken)\n const data = await response.json()\n const jsonResponse = {\n userinfo: data,\n accessToken,\n impersonatorUserId: userFromToken.impersonatorUserId\n }\n return new Response(JSON.stringify(jsonResponse), {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n }\n })\n } else if (response.status === 401) {\n return new Response(null, {status: 401})\n } else {\n return new Response(null, {status: 500})\n }\n }\n return new Response(null, {status: 401})\n }\n\n async function logoutPostHandler(req: NextRequest) {\n const refresh_token = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value\n if (!refresh_token) {\n const headers = new Headers()\n headers.append(\"Set-Cookie\", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n headers.append(\"Set-Cookie\", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n return new Response(null, {status: 200, headers})\n }\n\n const logoutBody = {refresh_token}\n const url = `${authUrlOrigin}/api/backend/v1/logout`\n const response = await fetch(url, {\n method: \"POST\",\n body: JSON.stringify(logoutBody),\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: \"Bearer \" + integrationApiKey,\n },\n })\n\n if (!response.ok) {\n console.log(\n \"Unable to logout, clearing cookies and continuing anyway\",\n response.status,\n response.statusText\n )\n }\n const headers = new Headers()\n headers.append(\"Set-Cookie\", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n headers.append(\"Set-Cookie\", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n return new Response(null, {status: 200, headers})\n }\n\n function getRouteHandler(req: NextRequest, {params}: { params: { slug: string } }) {\n if (params.slug === \"login\") {\n return loginGetHandler()\n } else if (params.slug === \"signup\") {\n return signupGetHandler()\n } else if (params.slug === \"callback\") {\n return callbackGetHandler(req)\n } else if (params.slug === \"userinfo\") {\n return userinfoGetHandler(req)\n } else {\n return new Response(\"\", {status: 404})\n }\n }\n\n function postRouteHandler(req: NextRequest, {params}: { params: { slug: string } }) {\n if (params.slug === \"logout\") {\n return logoutPostHandler(req)\n } else {\n return new Response(\"\", {status: 404})\n }\n }\n\n return {\n getRouteHandler,\n postRouteHandler\n }\n}\n\nfunction randomState(): string {\n const randomBytes = crypto.getRandomValues(new Uint8Array(32))\n return Array.from(randomBytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\")\n}\n\n","export class UserFromToken {\n public userId: string\n public orgIdToOrgMemberInfo?: OrgIdToOrgMemberInfo\n\n // Metadata about the user\n public email: string\n public firstName?: string\n public lastName?: string\n public username?: string\n\n // If you used our migration APIs to migrate this user from a different system,\n // this is their original ID from that system.\n public legacyUserId?: string\n public impersonatorUserId?: string\n\n constructor(\n userId: string,\n email: string,\n orgIdToOrgMemberInfo?: OrgIdToOrgMemberInfo,\n firstName?: string,\n lastName?: string,\n username?: string,\n legacyUserId?: string,\n impersonatorUserId?: string\n ) {\n this.userId = userId\n this.orgIdToOrgMemberInfo = orgIdToOrgMemberInfo\n\n this.email = email\n this.firstName = firstName\n this.lastName = lastName\n this.username = username\n\n this.legacyUserId = legacyUserId\n this.impersonatorUserId = impersonatorUserId\n }\n\n public getOrg(orgId: string): OrgMemberInfo | undefined {\n if (!this.orgIdToOrgMemberInfo) {\n return undefined\n }\n\n return this.orgIdToOrgMemberInfo[orgId]\n }\n\n public getOrgByName(orgName: string): OrgMemberInfo | undefined {\n if (!this.orgIdToOrgMemberInfo) {\n return undefined\n }\n\n const urlSafeOrgName = orgName.toLowerCase().replace(/ /g, \"-\")\n for (const orgId in this.orgIdToOrgMemberInfo) {\n const orgMemberInfo = this.orgIdToOrgMemberInfo[orgId]\n if (orgMemberInfo.urlSafeOrgName === urlSafeOrgName) {\n return orgMemberInfo\n }\n }\n\n return undefined\n }\n\n public getOrgs(): OrgMemberInfo[] {\n if (!this.orgIdToOrgMemberInfo) {\n return []\n }\n\n return Object.values(this.orgIdToOrgMemberInfo)\n }\n\n public isImpersonating(): boolean {\n return !!this.impersonatorUserId\n }\n\n public static fromJSON(json: string): UserFromToken {\n const obj = JSON.parse(json)\n const orgIdToOrgMemberInfo: OrgIdToOrgMemberInfo = {}\n for (const orgId in obj.orgIdToOrgMemberInfo) {\n orgIdToOrgMemberInfo[orgId] = OrgMemberInfo.fromJSON(\n JSON.stringify(obj.orgIdToOrgMemberInfo[orgId])\n )\n }\n return new UserFromToken(\n obj.userId,\n obj.email,\n orgIdToOrgMemberInfo,\n obj.firstName,\n obj.lastName,\n obj.username,\n obj.legacyUserId,\n obj.impersonatorUserId\n )\n }\n}\n\nexport type OrgIdToOrgMemberInfo = {\n [orgId: string]: OrgMemberInfo\n}\n\nexport class OrgMemberInfo {\n public orgId: string\n public orgName: string\n public orgMetadata: { [key: string]: any }\n public urlSafeOrgName: string\n\n private userAssignedRole: string\n private userInheritedRolesPlusCurrentRole: string[]\n private userPermissions: string[]\n\n constructor(\n orgId: string,\n orgName: string,\n orgMetadata: { [key: string]: any },\n urlSafeOrgName: string,\n userAssignedRole: string,\n userInheritedRolesPlusCurrentRole: string[],\n userPermissions: string[]\n ) {\n this.orgId = orgId\n this.orgName = orgName\n this.orgMetadata = orgMetadata\n this.urlSafeOrgName = urlSafeOrgName\n\n this.userAssignedRole = userAssignedRole\n this.userInheritedRolesPlusCurrentRole = userInheritedRolesPlusCurrentRole\n this.userPermissions = userPermissions\n }\n\n // validation methods\n\n public isRole(role: string): boolean {\n return this.userAssignedRole === role\n }\n\n public isAtLeastRole(role: string): boolean {\n return this.userInheritedRolesPlusCurrentRole.includes(role)\n }\n\n public hasPermission(permission: string): boolean {\n return this.userPermissions.includes(permission)\n }\n\n public hasAllPermissions(permissions: string[]): boolean {\n return permissions.every((permission) => this.hasPermission(permission))\n }\n\n public static fromJSON(json: string): OrgMemberInfo {\n const obj = JSON.parse(json)\n return new OrgMemberInfo(\n obj.orgId,\n obj.orgName,\n obj.orgMetadata,\n obj.urlSafeOrgName,\n obj.userAssignedRole,\n obj.userInheritedRolesPlusCurrentRole,\n obj.userPermissions\n )\n }\n\n // getters for the private fields\n\n get assignedRole(): string {\n return this.userAssignedRole\n }\n\n get inheritedRolesPlusCurrentRole(): string[] {\n return this.userInheritedRolesPlusCurrentRole\n }\n\n get permissions(): string[] {\n return this.userPermissions\n }\n}\n\n// These Internal types exist since the server returns snake case, but typescript/javascript\n// convention is camelCase.\nexport type InternalOrgMemberInfo = {\n org_id: string\n org_name: string\n org_metadata: { [key: string]: any }\n url_safe_org_name: string\n user_role: string\n inherited_user_roles_plus_current_role: string[]\n user_permissions: string[]\n}\nexport type InternalUser = {\n user_id: string\n org_id_to_org_member_info?: { [org_id: string]: InternalOrgMemberInfo }\n\n email: string\n first_name?: string\n last_name?: string\n username?: string\n\n // If you used our migration APIs to migrate this user from a different system, this is their original ID from that system.\n legacy_user_id?: string\n impersonatorUserId?: string\n}\n\nexport function toUser(snake_case: InternalUser): UserFromToken {\n return new UserFromToken(\n snake_case.user_id,\n snake_case.email,\n toOrgIdToOrgMemberInfo(snake_case.org_id_to_org_member_info),\n snake_case.first_name,\n snake_case.last_name,\n snake_case.username,\n snake_case.legacy_user_id,\n snake_case.impersonatorUserId\n )\n}\n\nexport function toOrgIdToOrgMemberInfo(snake_case?: {\n [org_id: string]: InternalOrgMemberInfo\n}): OrgIdToOrgMemberInfo | undefined {\n if (snake_case === undefined) {\n return undefined\n }\n const camelCase: OrgIdToOrgMemberInfo = {}\n\n for (const key of Object.keys(snake_case)) {\n const snakeCaseValue = snake_case[key]\n if (snakeCaseValue) {\n camelCase[key] = new OrgMemberInfo(\n snakeCaseValue.org_id,\n snakeCaseValue.org_name,\n snakeCaseValue.org_metadata,\n snakeCaseValue.url_safe_org_name,\n snakeCaseValue.user_role,\n snakeCaseValue.inherited_user_roles_plus_current_role,\n snakeCaseValue.user_permissions\n )\n }\n }\n\n return camelCase\n}\n","import {ResponseCookie} from \"next/dist/compiled/@edge-runtime/cookies\";\nimport {InternalUser, toUser, UserFromToken} from \"../user\";\nimport {ConfigurationException, UnauthorizedException} from \"./exceptions\";\nimport * as jose from \"jose\";\n\ntype RefreshAndAccessTokens = {\n refreshToken: string\n accessToken: string\n error: \"none\"\n}\n\ntype RefreshAndAccessTokensUnauthorizedError = {\n error: \"unauthorized\"\n}\n\ntype RefreshAndAccessTokensUnexpectedError = {\n error: \"unexpected\"\n}\n\nexport type RefreshTokenResponse =\n RefreshAndAccessTokens\n | RefreshAndAccessTokensUnauthorizedError\n | RefreshAndAccessTokensUnexpectedError\n\nexport const LOGIN_PATH = \"/api/auth/login\"\nexport const CALLBACK_PATH = \"/api/auth/callback\"\nexport const USERINFO_PATH = \"/api/auth/userinfo\"\nexport const LOGOUT_PATH = \"/api/auth/logout\"\nexport const ACCESS_TOKEN_COOKIE_NAME = \"__pa_at\"\nexport const REFRESH_TOKEN_COOKIE_NAME = \"__pa_rt\"\nexport const STATE_COOKIE_NAME = \"__pa_state\"\nexport const CUSTOM_HEADER_FOR_ACCESS_TOKEN = \"x-propelauth-access-token\"\n\nexport const COOKIE_OPTIONS: Partial<ResponseCookie> = {\n httpOnly: true,\n sameSite: \"lax\",\n secure: true,\n path: \"/\",\n}\n\nexport function getAuthUrlOrigin() {\n return getAuthUrl().origin\n}\n\nexport function getAuthUrl() {\n const authUrl = process.env.NEXT_PUBLIC_AUTH_URL\n if (!authUrl) {\n throw new Error(\"NEXT_PUBLIC_AUTH_URL is not set\")\n }\n return new URL(authUrl)\n}\n\nexport function getRedirectUri() {\n const redirectUri = process.env.PROPELAUTH_REDIRECT_URI\n if (!redirectUri) {\n throw new Error(\"PROPELAUTH_REDIRECT_URI is not set\")\n }\n return redirectUri\n}\n\nexport function getIntegrationApiKey() {\n const integrationApiKey = process.env.PROPELAUTH_API_KEY\n if (!integrationApiKey) {\n throw new Error(\"PROPELAUTH_API_KEY is not set\")\n }\n return integrationApiKey\n}\n\nexport function getVerifierKey() {\n const verifierKey = process.env.PROPELAUTH_VERIFIER_KEY\n if (!verifierKey) {\n throw new Error(\"PROPELAUTH_VERIFIER_KEY is not set\")\n }\n return verifierKey.replace(/\\\\n/g, \"\\n\")\n}\n\nexport async function refreshTokenWithAccessAndRefreshToken(refreshToken: string): Promise<RefreshTokenResponse> {\n const body = {\n refresh_token: refreshToken,\n }\n const url = `${getAuthUrlOrigin()}/api/backend/v1/refresh_token`\n const response = await fetch(url, {\n method: \"POST\",\n body: JSON.stringify(body),\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: \"Bearer \" + getIntegrationApiKey(),\n },\n })\n\n if (response.ok) {\n const data = await response.json()\n const newRefreshToken = data.refresh_token\n const {\n access_token: accessToken,\n expires_at_seconds: expiresAtSeconds,\n } = data.access_token\n\n return {\n refreshToken: newRefreshToken,\n accessToken,\n error: \"none\",\n }\n } else if (response.status === 400) {\n return {error: \"unauthorized\"}\n } else {\n return {error: \"unexpected\"}\n }\n}\n\nexport async function validateAccessTokenOrUndefined(accessToken: string | undefined): Promise<UserFromToken | undefined> {\n try {\n return await validateAccessToken(accessToken)\n } catch (err) {\n if (err instanceof ConfigurationException) {\n throw err\n } else if (err instanceof UnauthorizedException) {\n return undefined\n } else {\n console.log(\"Error validating access token\", err)\n return undefined\n }\n }\n}\n\nexport async function validateAccessToken(accessToken: string | undefined): Promise<UserFromToken> {\n let publicKey\n try {\n publicKey = await jose.importSPKI(getVerifierKey(), \"RS256\")\n } catch (err) {\n console.error(\"Verifier key is invalid. Make sure it's specified correctly, including the newlines.\", err)\n throw new ConfigurationException(\"Invalid verifier key\")\n }\n\n if (!accessToken) {\n throw new UnauthorizedException(\"No access token provided\")\n }\n\n let accessTokenWithoutBearer = accessToken\n if (accessToken.toLowerCase().startsWith(\"bearer \")) {\n accessTokenWithoutBearer = accessToken.substring(\"bearer \".length)\n }\n\n try {\n const {payload} = await jose.jwtVerify(accessTokenWithoutBearer, publicKey, {\n issuer: getAuthUrlOrigin(),\n algorithms: [\"RS256\"],\n })\n\n return toUser(<InternalUser>payload)\n } catch (e) {\n if (e instanceof Error) {\n throw new UnauthorizedException(e.message)\n } else {\n throw new UnauthorizedException(\"Unable to decode jwt\")\n }\n }\n}\n"],"mappings":"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","names":["headers","response"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/server/app-router-index.ts","../../../src/server/exceptions.ts","../../../src/server/app-router.ts","../../../src/user.ts","../../../src/server/shared.ts"],"sourcesContent":["export {UnauthorizedException, ConfigurationException} from \"./exceptions\"\nexport {getRouteHandlers, getUser, getUserOrRedirect, getAccessToken, authMiddleware} from \"./app-router\"\nexport type {RouteHandlerArgs} from \"./app-router\"\n","export class UnauthorizedException extends Error {\n readonly message: string\n readonly status: number\n\n constructor(message: string) {\n super(message)\n this.message = message\n this.status = 401\n }\n}\n\nexport class ConfigurationException extends Error {\n readonly message: string\n readonly status: number\n\n constructor(message: string) {\n super(message)\n this.message = message\n this.status = 500\n }\n}\n","import {redirect} from \"next/navigation.js\";\nimport {cookies, headers} from \"next/headers.js\";\nimport {NextRequest, NextResponse} from \"next/server.js\";\nimport {\n ACCESS_TOKEN_COOKIE_NAME,\n CALLBACK_PATH,\n COOKIE_OPTIONS,\n CUSTOM_HEADER_FOR_ACCESS_TOKEN,\n getAuthUrlOrigin,\n getIntegrationApiKey,\n getRedirectUri,\n LOGIN_PATH,\n LOGOUT_PATH,\n REFRESH_TOKEN_COOKIE_NAME,\n refreshTokenWithAccessAndRefreshToken,\n STATE_COOKIE_NAME,\n USERINFO_PATH,\n validateAccessToken,\n validateAccessTokenOrUndefined\n} from \"./shared\";\nimport {UserFromToken} from \"./index\"\n\nexport async function getUserOrRedirect(): Promise<UserFromToken> {\n const user = await getUser()\n if (user) {\n return user\n } else {\n redirect(LOGIN_PATH)\n throw new Error(\"Redirecting to login\")\n }\n}\n\nexport async function getUser(): Promise<UserFromToken | undefined> {\n const accessToken = headers().get(CUSTOM_HEADER_FOR_ACCESS_TOKEN) || cookies().get(ACCESS_TOKEN_COOKIE_NAME)?.value\n if (accessToken) {\n const user = await validateAccessTokenOrUndefined(accessToken)\n if (user) {\n return user\n }\n }\n return undefined\n}\n\nexport async function getAccessToken(): Promise<string | undefined> {\n return headers().get(CUSTOM_HEADER_FOR_ACCESS_TOKEN) || cookies().get(ACCESS_TOKEN_COOKIE_NAME)?.value\n}\n\n// Purpose of this middleware is just to keep the access token cookie alive\n// In an ideal world, this could be done in `getUser`, however, you can't\n// set a cookie in a server component.\n// There also doesn't seem to be any way right now to set a cookie in a\n// middleware and pass it forward (you can only set them on the response).\n// You CAN, however, pass in custom headers,\n// so we'll use CUSTOM_HEADER_FOR_ACCESS_TOKEN as a workaround\nexport async function authMiddleware(req: NextRequest): Promise<Response> {\n if (req.headers.has(CUSTOM_HEADER_FOR_ACCESS_TOKEN)) {\n throw new Error(`${CUSTOM_HEADER_FOR_ACCESS_TOKEN} is set which is for internal use only`)\n } else if (req.nextUrl.pathname === CALLBACK_PATH || req.nextUrl.pathname === LOGOUT_PATH || req.nextUrl.pathname === USERINFO_PATH) {\n // Don't do anything for the callback, logout, or userinfo paths, as they will modify the cookies themselves\n return NextResponse.next()\n }\n\n const accessToken = req.cookies.get(ACCESS_TOKEN_COOKIE_NAME)?.value\n const refreshToken = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value\n\n // If we are authenticated, we can continue\n if (accessToken) {\n const user = await validateAccessTokenOrUndefined(accessToken)\n if (user) {\n return NextResponse.next()\n }\n }\n\n // Otherwise, we need to refresh the access token\n if (refreshToken) {\n const response = await refreshTokenWithAccessAndRefreshToken(refreshToken)\n if (response.error === \"unexpected\") {\n throw new Error(\"Unexpected error while refreshing access token\")\n } else if (response.error === \"unauthorized\") {\n const response = NextResponse.next()\n response.cookies.delete(ACCESS_TOKEN_COOKIE_NAME)\n response.cookies.delete(REFRESH_TOKEN_COOKIE_NAME)\n return response\n } else {\n const headers = new Headers(req.headers)\n // Pass along the new access token in a header since cookies don't work\n headers.append(CUSTOM_HEADER_FOR_ACCESS_TOKEN, response.accessToken)\n const nextResponse = NextResponse.next({\n request: {\n headers\n }\n })\n nextResponse.cookies.set(ACCESS_TOKEN_COOKIE_NAME, response.accessToken, COOKIE_OPTIONS)\n nextResponse.cookies.set(REFRESH_TOKEN_COOKIE_NAME, response.refreshToken, COOKIE_OPTIONS)\n return nextResponse\n }\n }\n\n return NextResponse.next()\n}\n\nexport type RouteHandlerArgs = {\n postLoginRedirectPathFn?: (req: NextRequest) => string\n}\n\nexport function getRouteHandlers(args?: RouteHandlerArgs) {\n const authUrlOrigin = getAuthUrlOrigin()\n const redirectUri = getRedirectUri()\n const integrationApiKey = getIntegrationApiKey()\n\n function loginGetHandler() {\n const state = randomState()\n const authorize_url =\n authUrlOrigin + \"/propelauth/ssr/authorize?redirect_uri=\" + redirectUri + \"&state=\" + state\n return new Response(null, {\n status: 302,\n headers: {\n Location: authorize_url,\n \"Set-Cookie\": `${STATE_COOKIE_NAME}=${state}; Path=/; HttpOnly; Secure; SameSite=Lax`,\n }\n })\n }\n\n function signupGetHandler() {\n const state = randomState()\n const authorize_url =\n getAuthUrlOrigin() + \"/propelauth/ssr/authorize?redirect_uri=\" + redirectUri + \"&state=\" + state + \"&signup=true\"\n return new Response(null, {\n status: 302,\n headers: {\n Location: authorize_url,\n \"Set-Cookie\": `${STATE_COOKIE_NAME}=${state}; Path=/; HttpOnly; Secure; SameSite=Lax`,\n }\n })\n }\n\n async function callbackGetHandler(req: NextRequest) {\n const oauthState = req.cookies.get(STATE_COOKIE_NAME)?.value\n if (!oauthState || oauthState.length !== 64) {\n return new Response(null, {status: 302, headers: {Location: LOGIN_PATH}})\n }\n\n const queryParams = req.nextUrl.searchParams\n const state = queryParams.get(\"state\")\n const code = queryParams.get(\"code\")\n if (state !== oauthState) {\n return new Response(null, {status: 302, headers: {Location: LOGIN_PATH}})\n }\n\n const oauth_token_body = {\n redirect_uri: redirectUri,\n code,\n }\n const url = `${authUrlOrigin}/propelauth/ssr/token`\n const response = await fetch(url, {\n method: \"POST\",\n body: JSON.stringify(oauth_token_body),\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: \"Bearer \" + integrationApiKey,\n },\n })\n\n if (response.ok) {\n const data = await response.json()\n\n const accessToken = data.access_token\n const path = args?.postLoginRedirectPathFn ? args.postLoginRedirectPathFn(req) : \"/\"\n if (!path) {\n console.log(\"postLoginPathFn returned undefined\")\n return new Response(\"Unexpected error\", {status: 500})\n }\n\n const headers = new Headers()\n headers.append(\"Location\", path)\n headers.append(\"Set-Cookie\", `${ACCESS_TOKEN_COOKIE_NAME}=${accessToken}; Path=/; HttpOnly; Secure; SameSite=Lax`)\n headers.append(\"Set-Cookie\", `${REFRESH_TOKEN_COOKIE_NAME}=${data.refresh_token}; Path=/; HttpOnly; Secure; SameSite=Lax`)\n return new Response(null, {\n status: 302,\n headers\n })\n } else if (response.status === 401) {\n return new Response(\"Unexpected error\", {status: 500})\n } else {\n return new Response(\"Unexpected error\", {status: 500})\n }\n }\n\n async function userinfoGetHandler(req: NextRequest) {\n const oldRefreshToken = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value\n\n // For the userinfo endpoint, we want to get the most up-to-date info, so we'll refresh the access token\n if (oldRefreshToken) {\n const refreshResponse = await refreshTokenWithAccessAndRefreshToken(oldRefreshToken)\n if (refreshResponse.error === \"unexpected\") {\n throw new Error(\"Unexpected error while refreshing access token\")\n } else if (refreshResponse.error === \"unauthorized\") {\n const headers = new Headers()\n headers.append(\"Set-Cookie\", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n headers.append(\"Set-Cookie\", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n return new Response(\"Unauthorized\", {status: 401, headers})\n }\n\n const refreshToken = refreshResponse.refreshToken\n const accessToken = refreshResponse.accessToken\n\n const path = `${authUrlOrigin}/propelauth/oauth/userinfo`\n const response = await fetch(path, {\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"Bearer \" + accessToken,\n }\n })\n if (response.ok) {\n const userFromToken = await validateAccessToken(accessToken)\n const data = await response.json()\n const jsonResponse = {\n userinfo: data,\n accessToken,\n impersonatorUserId: userFromToken.impersonatorUserId\n }\n\n const headers = new Headers()\n headers.append(\"Set-Cookie\", `${ACCESS_TOKEN_COOKIE_NAME}=${accessToken}; Path=/; HttpOnly; Secure; SameSite=Lax`)\n headers.append(\"Set-Cookie\", `${REFRESH_TOKEN_COOKIE_NAME}=${refreshToken}; Path=/; HttpOnly; Secure; SameSite=Lax`)\n headers.append(\"Content-Type\", \"application/json\")\n return new Response(JSON.stringify(jsonResponse), {\n status: 200,\n headers\n })\n } else if (response.status === 401) {\n const headers = new Headers()\n headers.append(\"Set-Cookie\", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n headers.append(\"Set-Cookie\", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n return new Response(null, {\n status: 401,\n headers\n })\n } else {\n return new Response(null, {status: 500})\n }\n }\n\n const headers = new Headers()\n headers.append(\"Set-Cookie\", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n headers.append(\"Set-Cookie\", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n return new Response(null, {status: 401})\n }\n\n async function logoutGetHandler(req: NextRequest) {\n // Real logout requests will go to the logout POST handler\n // This endpoint is a landing page for when people logout from the hosted UIs\n // Instead of doing a logout we'll check the refresh token.\n // If it's invalid, we'll clear the cookies and redirect using the postLoginRedirectPathFn\n const path = args?.postLoginRedirectPathFn ? args.postLoginRedirectPathFn(req) : \"/\"\n if (!path) {\n console.log(\"postLoginPathFn returned undefined\")\n return new Response(\"Unexpected error\", {status: 500})\n }\n\n const refreshToken = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value\n if (!refreshToken) {\n const headers = new Headers()\n headers.append(\"Location\", path)\n headers.append(\"Set-Cookie\", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n headers.append(\"Set-Cookie\", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n return new Response(null, {\n status: 302,\n headers\n })\n }\n\n const refreshResponse = await refreshTokenWithAccessAndRefreshToken(refreshToken)\n if (refreshResponse.error === \"unexpected\") {\n console.error(\"Unexpected error while refreshing access token\")\n return new Response(\"Unexpected error\", {status: 500})\n } else if (refreshResponse.error === \"unauthorized\") {\n const headers = new Headers()\n headers.append(\"Location\", path)\n headers.append(\"Set-Cookie\", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n headers.append(\"Set-Cookie\", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n return new Response(null, {\n status: 302,\n headers\n })\n } else {\n const headers = new Headers()\n headers.append(\"Location\", path)\n return new Response(null, {\n status: 302,\n headers\n })\n }\n }\n\n async function logoutPostHandler(req: NextRequest) {\n const refreshToken = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value\n if (!refreshToken) {\n const headers = new Headers()\n headers.append(\"Set-Cookie\", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n headers.append(\"Set-Cookie\", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n return new Response(null, {status: 200, headers})\n }\n\n const logoutBody = {refresh_token: refreshToken}\n const url = `${authUrlOrigin}/api/backend/v1/logout`\n const response = await fetch(url, {\n method: \"POST\",\n body: JSON.stringify(logoutBody),\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: \"Bearer \" + integrationApiKey,\n },\n })\n\n if (!response.ok) {\n console.log(\n \"Unable to logout, clearing cookies and continuing anyway\",\n response.status,\n response.statusText\n )\n }\n const headers = new Headers()\n headers.append(\"Set-Cookie\", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n headers.append(\"Set-Cookie\", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`)\n return new Response(null, {status: 200, headers})\n }\n\n function getRouteHandler(req: NextRequest, {params}: { params: { slug: string } }) {\n if (params.slug === \"login\") {\n return loginGetHandler()\n } else if (params.slug === \"signup\") {\n return signupGetHandler()\n } else if (params.slug === \"callback\") {\n return callbackGetHandler(req)\n } else if (params.slug === \"userinfo\") {\n return userinfoGetHandler(req)\n } else if (params.slug === \"logout\") {\n return logoutGetHandler(req)\n } else {\n return new Response(\"\", {status: 404})\n }\n }\n\n function postRouteHandler(req: NextRequest, {params}: { params: { slug: string } }) {\n if (params.slug === \"logout\") {\n return logoutPostHandler(req)\n } else {\n return new Response(\"\", {status: 404})\n }\n }\n\n return {\n getRouteHandler,\n postRouteHandler\n }\n}\n\nfunction randomState(): string {\n const randomBytes = crypto.getRandomValues(new Uint8Array(32))\n return Array.from(randomBytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\")\n}\n\n","export class UserFromToken {\n public userId: string\n public orgIdToOrgMemberInfo?: OrgIdToOrgMemberInfo\n\n // Metadata about the user\n public email: string\n public firstName?: string\n public lastName?: string\n public username?: string\n\n // If you used our migration APIs to migrate this user from a different system,\n // this is their original ID from that system.\n public legacyUserId?: string\n public impersonatorUserId?: string\n\n constructor(\n userId: string,\n email: string,\n orgIdToOrgMemberInfo?: OrgIdToOrgMemberInfo,\n firstName?: string,\n lastName?: string,\n username?: string,\n legacyUserId?: string,\n impersonatorUserId?: string\n ) {\n this.userId = userId\n this.orgIdToOrgMemberInfo = orgIdToOrgMemberInfo\n\n this.email = email\n this.firstName = firstName\n this.lastName = lastName\n this.username = username\n\n this.legacyUserId = legacyUserId\n this.impersonatorUserId = impersonatorUserId\n }\n\n public getOrg(orgId: string): OrgMemberInfo | undefined {\n if (!this.orgIdToOrgMemberInfo) {\n return undefined\n }\n\n return this.orgIdToOrgMemberInfo[orgId]\n }\n\n public getOrgByName(orgName: string): OrgMemberInfo | undefined {\n if (!this.orgIdToOrgMemberInfo) {\n return undefined\n }\n\n const urlSafeOrgName = orgName.toLowerCase().replace(/ /g, \"-\")\n for (const orgId in this.orgIdToOrgMemberInfo) {\n const orgMemberInfo = this.orgIdToOrgMemberInfo[orgId]\n if (orgMemberInfo.urlSafeOrgName === urlSafeOrgName) {\n return orgMemberInfo\n }\n }\n\n return undefined\n }\n\n public getOrgs(): OrgMemberInfo[] {\n if (!this.orgIdToOrgMemberInfo) {\n return []\n }\n\n return Object.values(this.orgIdToOrgMemberInfo)\n }\n\n public isImpersonating(): boolean {\n return !!this.impersonatorUserId\n }\n\n public static fromJSON(json: string): UserFromToken {\n const obj = JSON.parse(json)\n const orgIdToOrgMemberInfo: OrgIdToOrgMemberInfo = {}\n for (const orgId in obj.orgIdToOrgMemberInfo) {\n orgIdToOrgMemberInfo[orgId] = OrgMemberInfo.fromJSON(\n JSON.stringify(obj.orgIdToOrgMemberInfo[orgId])\n )\n }\n return new UserFromToken(\n obj.userId,\n obj.email,\n orgIdToOrgMemberInfo,\n obj.firstName,\n obj.lastName,\n obj.username,\n obj.legacyUserId,\n obj.impersonatorUserId\n )\n }\n}\n\nexport type OrgIdToOrgMemberInfo = {\n [orgId: string]: OrgMemberInfo\n}\n\nexport class OrgMemberInfo {\n public orgId: string\n public orgName: string\n public orgMetadata: { [key: string]: any }\n public urlSafeOrgName: string\n\n private userAssignedRole: string\n private userInheritedRolesPlusCurrentRole: string[]\n private userPermissions: string[]\n\n constructor(\n orgId: string,\n orgName: string,\n orgMetadata: { [key: string]: any },\n urlSafeOrgName: string,\n userAssignedRole: string,\n userInheritedRolesPlusCurrentRole: string[],\n userPermissions: string[]\n ) {\n this.orgId = orgId\n this.orgName = orgName\n this.orgMetadata = orgMetadata\n this.urlSafeOrgName = urlSafeOrgName\n\n this.userAssignedRole = userAssignedRole\n this.userInheritedRolesPlusCurrentRole = userInheritedRolesPlusCurrentRole\n this.userPermissions = userPermissions\n }\n\n // validation methods\n\n public isRole(role: string): boolean {\n return this.userAssignedRole === role\n }\n\n public isAtLeastRole(role: string): boolean {\n return this.userInheritedRolesPlusCurrentRole.includes(role)\n }\n\n public hasPermission(permission: string): boolean {\n return this.userPermissions.includes(permission)\n }\n\n public hasAllPermissions(permissions: string[]): boolean {\n return permissions.every((permission) => this.hasPermission(permission))\n }\n\n public static fromJSON(json: string): OrgMemberInfo {\n const obj = JSON.parse(json)\n return new OrgMemberInfo(\n obj.orgId,\n obj.orgName,\n obj.orgMetadata,\n obj.urlSafeOrgName,\n obj.userAssignedRole,\n obj.userInheritedRolesPlusCurrentRole,\n obj.userPermissions\n )\n }\n\n // getters for the private fields\n\n get assignedRole(): string {\n return this.userAssignedRole\n }\n\n get inheritedRolesPlusCurrentRole(): string[] {\n return this.userInheritedRolesPlusCurrentRole\n }\n\n get permissions(): string[] {\n return this.userPermissions\n }\n}\n\n// These Internal types exist since the server returns snake case, but typescript/javascript\n// convention is camelCase.\nexport type InternalOrgMemberInfo = {\n org_id: string\n org_name: string\n org_metadata: { [key: string]: any }\n url_safe_org_name: string\n user_role: string\n inherited_user_roles_plus_current_role: string[]\n user_permissions: string[]\n}\nexport type InternalUser = {\n user_id: string\n org_id_to_org_member_info?: { [org_id: string]: InternalOrgMemberInfo }\n\n email: string\n first_name?: string\n last_name?: string\n username?: string\n\n // If you used our migration APIs to migrate this user from a different system, this is their original ID from that system.\n legacy_user_id?: string\n impersonatorUserId?: string\n}\n\nexport function toUser(snake_case: InternalUser): UserFromToken {\n return new UserFromToken(\n snake_case.user_id,\n snake_case.email,\n toOrgIdToOrgMemberInfo(snake_case.org_id_to_org_member_info),\n snake_case.first_name,\n snake_case.last_name,\n snake_case.username,\n snake_case.legacy_user_id,\n snake_case.impersonatorUserId\n )\n}\n\nexport function toOrgIdToOrgMemberInfo(snake_case?: {\n [org_id: string]: InternalOrgMemberInfo\n}): OrgIdToOrgMemberInfo | undefined {\n if (snake_case === undefined) {\n return undefined\n }\n const camelCase: OrgIdToOrgMemberInfo = {}\n\n for (const key of Object.keys(snake_case)) {\n const snakeCaseValue = snake_case[key]\n if (snakeCaseValue) {\n camelCase[key] = new OrgMemberInfo(\n snakeCaseValue.org_id,\n snakeCaseValue.org_name,\n snakeCaseValue.org_metadata,\n snakeCaseValue.url_safe_org_name,\n snakeCaseValue.user_role,\n snakeCaseValue.inherited_user_roles_plus_current_role,\n snakeCaseValue.user_permissions\n )\n }\n }\n\n return camelCase\n}\n","import {ResponseCookie} from \"next/dist/compiled/@edge-runtime/cookies\";\nimport {InternalUser, toUser, UserFromToken} from \"../user\";\nimport {ConfigurationException, UnauthorizedException} from \"./exceptions\";\nimport * as jose from \"jose\";\n\ntype RefreshAndAccessTokens = {\n refreshToken: string\n accessToken: string\n error: \"none\"\n}\n\ntype RefreshAndAccessTokensUnauthorizedError = {\n error: \"unauthorized\"\n}\n\ntype RefreshAndAccessTokensUnexpectedError = {\n error: \"unexpected\"\n}\n\nexport type RefreshTokenResponse =\n RefreshAndAccessTokens\n | RefreshAndAccessTokensUnauthorizedError\n | RefreshAndAccessTokensUnexpectedError\n\nexport const LOGIN_PATH = \"/api/auth/login\"\nexport const CALLBACK_PATH = \"/api/auth/callback\"\nexport const USERINFO_PATH = \"/api/auth/userinfo\"\nexport const LOGOUT_PATH = \"/api/auth/logout\"\nexport const ACCESS_TOKEN_COOKIE_NAME = \"__pa_at\"\nexport const REFRESH_TOKEN_COOKIE_NAME = \"__pa_rt\"\nexport const STATE_COOKIE_NAME = \"__pa_state\"\nexport const CUSTOM_HEADER_FOR_ACCESS_TOKEN = \"x-propelauth-access-token\"\n\nexport const COOKIE_OPTIONS: Partial<ResponseCookie> = {\n httpOnly: true,\n sameSite: \"lax\",\n secure: true,\n path: \"/\",\n}\n\nexport function getAuthUrlOrigin() {\n return getAuthUrl().origin\n}\n\nexport function getAuthUrl() {\n const authUrl = process.env.NEXT_PUBLIC_AUTH_URL\n if (!authUrl) {\n throw new Error(\"NEXT_PUBLIC_AUTH_URL is not set\")\n }\n return new URL(authUrl)\n}\n\nexport function getRedirectUri() {\n const redirectUri = process.env.PROPELAUTH_REDIRECT_URI\n if (!redirectUri) {\n throw new Error(\"PROPELAUTH_REDIRECT_URI is not set\")\n }\n return redirectUri\n}\n\nexport function getIntegrationApiKey() {\n const integrationApiKey = process.env.PROPELAUTH_API_KEY\n if (!integrationApiKey) {\n throw new Error(\"PROPELAUTH_API_KEY is not set\")\n }\n return integrationApiKey\n}\n\nexport function getVerifierKey() {\n const verifierKey = process.env.PROPELAUTH_VERIFIER_KEY\n if (!verifierKey) {\n throw new Error(\"PROPELAUTH_VERIFIER_KEY is not set\")\n }\n return verifierKey.replace(/\\\\n/g, \"\\n\")\n}\n\nexport async function refreshTokenWithAccessAndRefreshToken(refreshToken: string): Promise<RefreshTokenResponse> {\n const body = {\n refresh_token: refreshToken,\n }\n const url = `${getAuthUrlOrigin()}/api/backend/v1/refresh_token`\n const response = await fetch(url, {\n method: \"POST\",\n body: JSON.stringify(body),\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: \"Bearer \" + getIntegrationApiKey(),\n },\n })\n\n if (response.ok) {\n const data = await response.json()\n const newRefreshToken = data.refresh_token\n const {\n access_token: accessToken,\n expires_at_seconds: expiresAtSeconds,\n } = data.access_token\n\n return {\n refreshToken: newRefreshToken,\n accessToken,\n error: \"none\",\n }\n } else if (response.status === 400 || response.status === 401) {\n return {error: \"unauthorized\"}\n } else {\n return {error: \"unexpected\"}\n }\n}\n\nexport async function validateAccessTokenOrUndefined(accessToken: string | undefined): Promise<UserFromToken | undefined> {\n try {\n return await validateAccessToken(accessToken)\n } catch (err) {\n if (err instanceof ConfigurationException) {\n throw err\n } else if (err instanceof UnauthorizedException) {\n return undefined\n } else {\n console.log(\"Error validating access token\", err)\n return undefined\n }\n }\n}\n\nexport async function validateAccessToken(accessToken: string | undefined): Promise<UserFromToken> {\n let publicKey\n try {\n publicKey = await jose.importSPKI(getVerifierKey(), \"RS256\")\n } catch (err) {\n console.error(\"Verifier key is invalid. Make sure it's specified correctly, including the newlines.\", err)\n throw new ConfigurationException(\"Invalid verifier key\")\n }\n\n if (!accessToken) {\n throw new UnauthorizedException(\"No access token provided\")\n }\n\n let accessTokenWithoutBearer = accessToken\n if (accessToken.toLowerCase().startsWith(\"bearer \")) {\n accessTokenWithoutBearer = accessToken.substring(\"bearer \".length)\n }\n\n try {\n const {payload} = await jose.jwtVerify(accessTokenWithoutBearer, publicKey, {\n issuer: getAuthUrlOrigin(),\n algorithms: [\"RS256\"],\n })\n\n return toUser(<InternalUser>payload)\n } catch (e) {\n if (e instanceof Error) {\n throw new UnauthorizedException(e.message)\n } else {\n throw new UnauthorizedException(\"Unable to decode jwt\")\n }\n }\n}\n"],"mappings":"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","names":["response","headers"]}
|
|
@@ -253,7 +253,7 @@ function refreshTokenWithAccessAndRefreshToken(refreshToken) {
|
|
|
253
253
|
accessToken,
|
|
254
254
|
error: "none"
|
|
255
255
|
};
|
|
256
|
-
} else if (response.status === 400) {
|
|
256
|
+
} else if (response.status === 400 || response.status === 401) {
|
|
257
257
|
return { error: "unauthorized" };
|
|
258
258
|
} else {
|
|
259
259
|
return { error: "unexpected" };
|
|
@@ -344,33 +344,11 @@ function authMiddleware(req) {
|
|
|
344
344
|
var _a, _b;
|
|
345
345
|
if (req.headers.has(CUSTOM_HEADER_FOR_ACCESS_TOKEN)) {
|
|
346
346
|
throw new Error(`${CUSTOM_HEADER_FOR_ACCESS_TOKEN} is set which is for internal use only`);
|
|
347
|
-
} else if (req.nextUrl.pathname === CALLBACK_PATH || req.nextUrl.pathname === LOGOUT_PATH) {
|
|
347
|
+
} else if (req.nextUrl.pathname === CALLBACK_PATH || req.nextUrl.pathname === LOGOUT_PATH || req.nextUrl.pathname === USERINFO_PATH) {
|
|
348
348
|
return NextResponse.next();
|
|
349
349
|
}
|
|
350
350
|
const accessToken = (_a = req.cookies.get(ACCESS_TOKEN_COOKIE_NAME)) == null ? void 0 : _a.value;
|
|
351
351
|
const refreshToken = (_b = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)) == null ? void 0 : _b.value;
|
|
352
|
-
if (req.nextUrl.pathname === USERINFO_PATH && refreshToken) {
|
|
353
|
-
const response = yield refreshTokenWithAccessAndRefreshToken(refreshToken);
|
|
354
|
-
if (response.error === "unexpected") {
|
|
355
|
-
throw new Error("Unexpected error while refreshing access token");
|
|
356
|
-
} else if (response.error === "unauthorized") {
|
|
357
|
-
const headers2 = new Headers();
|
|
358
|
-
headers2.append("Set-Cookie", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
359
|
-
headers2.append("Set-Cookie", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
360
|
-
return new Response("Unauthorized", { status: 401, headers: headers2 });
|
|
361
|
-
} else {
|
|
362
|
-
const headers2 = new Headers(req.headers);
|
|
363
|
-
headers2.append(CUSTOM_HEADER_FOR_ACCESS_TOKEN, response.accessToken);
|
|
364
|
-
const nextResponse = NextResponse.next({
|
|
365
|
-
request: {
|
|
366
|
-
headers: headers2
|
|
367
|
-
}
|
|
368
|
-
});
|
|
369
|
-
nextResponse.cookies.set(ACCESS_TOKEN_COOKIE_NAME, response.accessToken, COOKIE_OPTIONS);
|
|
370
|
-
nextResponse.cookies.set(REFRESH_TOKEN_COOKIE_NAME, response.refreshToken, COOKIE_OPTIONS);
|
|
371
|
-
return nextResponse;
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
352
|
if (accessToken) {
|
|
375
353
|
const user = yield validateAccessTokenOrUndefined(accessToken);
|
|
376
354
|
if (user) {
|
|
@@ -433,14 +411,12 @@ function getRouteHandlers(args) {
|
|
|
433
411
|
var _a;
|
|
434
412
|
const oauthState = (_a = req.cookies.get(STATE_COOKIE_NAME)) == null ? void 0 : _a.value;
|
|
435
413
|
if (!oauthState || oauthState.length !== 64) {
|
|
436
|
-
console.log("No oauth state found");
|
|
437
414
|
return new Response(null, { status: 302, headers: { Location: LOGIN_PATH } });
|
|
438
415
|
}
|
|
439
416
|
const queryParams = req.nextUrl.searchParams;
|
|
440
417
|
const state = queryParams.get("state");
|
|
441
418
|
const code = queryParams.get("code");
|
|
442
419
|
if (state !== oauthState) {
|
|
443
|
-
console.log("Mismatch between states, redirecting to login");
|
|
444
420
|
return new Response(null, { status: 302, headers: { Location: LOGIN_PATH } });
|
|
445
421
|
}
|
|
446
422
|
const oauth_token_body = {
|
|
@@ -482,8 +458,19 @@ function getRouteHandlers(args) {
|
|
|
482
458
|
function userinfoGetHandler(req) {
|
|
483
459
|
return __async(this, null, function* () {
|
|
484
460
|
var _a;
|
|
485
|
-
const
|
|
486
|
-
if (
|
|
461
|
+
const oldRefreshToken = (_a = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)) == null ? void 0 : _a.value;
|
|
462
|
+
if (oldRefreshToken) {
|
|
463
|
+
const refreshResponse = yield refreshTokenWithAccessAndRefreshToken(oldRefreshToken);
|
|
464
|
+
if (refreshResponse.error === "unexpected") {
|
|
465
|
+
throw new Error("Unexpected error while refreshing access token");
|
|
466
|
+
} else if (refreshResponse.error === "unauthorized") {
|
|
467
|
+
const headers3 = new Headers();
|
|
468
|
+
headers3.append("Set-Cookie", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
469
|
+
headers3.append("Set-Cookie", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
470
|
+
return new Response("Unauthorized", { status: 401, headers: headers3 });
|
|
471
|
+
}
|
|
472
|
+
const refreshToken = refreshResponse.refreshToken;
|
|
473
|
+
const accessToken = refreshResponse.accessToken;
|
|
487
474
|
const path = `${authUrlOrigin}/propelauth/oauth/userinfo`;
|
|
488
475
|
const response = yield fetch(path, {
|
|
489
476
|
headers: {
|
|
@@ -499,32 +486,85 @@ function getRouteHandlers(args) {
|
|
|
499
486
|
accessToken,
|
|
500
487
|
impersonatorUserId: userFromToken.impersonatorUserId
|
|
501
488
|
};
|
|
489
|
+
const headers3 = new Headers();
|
|
490
|
+
headers3.append("Set-Cookie", `${ACCESS_TOKEN_COOKIE_NAME}=${accessToken}; Path=/; HttpOnly; Secure; SameSite=Lax`);
|
|
491
|
+
headers3.append("Set-Cookie", `${REFRESH_TOKEN_COOKIE_NAME}=${refreshToken}; Path=/; HttpOnly; Secure; SameSite=Lax`);
|
|
492
|
+
headers3.append("Content-Type", "application/json");
|
|
502
493
|
return new Response(JSON.stringify(jsonResponse), {
|
|
503
494
|
status: 200,
|
|
504
|
-
headers:
|
|
505
|
-
"Content-Type": "application/json"
|
|
506
|
-
}
|
|
495
|
+
headers: headers3
|
|
507
496
|
});
|
|
508
497
|
} else if (response.status === 401) {
|
|
509
|
-
|
|
498
|
+
const headers3 = new Headers();
|
|
499
|
+
headers3.append("Set-Cookie", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
500
|
+
headers3.append("Set-Cookie", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
501
|
+
return new Response(null, {
|
|
502
|
+
status: 401,
|
|
503
|
+
headers: headers3
|
|
504
|
+
});
|
|
510
505
|
} else {
|
|
511
506
|
return new Response(null, { status: 500 });
|
|
512
507
|
}
|
|
513
508
|
}
|
|
509
|
+
const headers2 = new Headers();
|
|
510
|
+
headers2.append("Set-Cookie", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
511
|
+
headers2.append("Set-Cookie", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
514
512
|
return new Response(null, { status: 401 });
|
|
515
513
|
});
|
|
516
514
|
}
|
|
515
|
+
function logoutGetHandler(req) {
|
|
516
|
+
return __async(this, null, function* () {
|
|
517
|
+
var _a;
|
|
518
|
+
const path = (args == null ? void 0 : args.postLoginRedirectPathFn) ? args.postLoginRedirectPathFn(req) : "/";
|
|
519
|
+
if (!path) {
|
|
520
|
+
console.log("postLoginPathFn returned undefined");
|
|
521
|
+
return new Response("Unexpected error", { status: 500 });
|
|
522
|
+
}
|
|
523
|
+
const refreshToken = (_a = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)) == null ? void 0 : _a.value;
|
|
524
|
+
if (!refreshToken) {
|
|
525
|
+
const headers2 = new Headers();
|
|
526
|
+
headers2.append("Location", path);
|
|
527
|
+
headers2.append("Set-Cookie", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
528
|
+
headers2.append("Set-Cookie", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
529
|
+
return new Response(null, {
|
|
530
|
+
status: 302,
|
|
531
|
+
headers: headers2
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
const refreshResponse = yield refreshTokenWithAccessAndRefreshToken(refreshToken);
|
|
535
|
+
if (refreshResponse.error === "unexpected") {
|
|
536
|
+
console.error("Unexpected error while refreshing access token");
|
|
537
|
+
return new Response("Unexpected error", { status: 500 });
|
|
538
|
+
} else if (refreshResponse.error === "unauthorized") {
|
|
539
|
+
const headers2 = new Headers();
|
|
540
|
+
headers2.append("Location", path);
|
|
541
|
+
headers2.append("Set-Cookie", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
542
|
+
headers2.append("Set-Cookie", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
543
|
+
return new Response(null, {
|
|
544
|
+
status: 302,
|
|
545
|
+
headers: headers2
|
|
546
|
+
});
|
|
547
|
+
} else {
|
|
548
|
+
const headers2 = new Headers();
|
|
549
|
+
headers2.append("Location", path);
|
|
550
|
+
return new Response(null, {
|
|
551
|
+
status: 302,
|
|
552
|
+
headers: headers2
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
}
|
|
517
557
|
function logoutPostHandler(req) {
|
|
518
558
|
return __async(this, null, function* () {
|
|
519
559
|
var _a;
|
|
520
|
-
const
|
|
521
|
-
if (!
|
|
560
|
+
const refreshToken = (_a = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)) == null ? void 0 : _a.value;
|
|
561
|
+
if (!refreshToken) {
|
|
522
562
|
const headers3 = new Headers();
|
|
523
563
|
headers3.append("Set-Cookie", `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
524
564
|
headers3.append("Set-Cookie", `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`);
|
|
525
565
|
return new Response(null, { status: 200, headers: headers3 });
|
|
526
566
|
}
|
|
527
|
-
const logoutBody = { refresh_token };
|
|
567
|
+
const logoutBody = { refresh_token: refreshToken };
|
|
528
568
|
const url = `${authUrlOrigin}/api/backend/v1/logout`;
|
|
529
569
|
const response = yield fetch(url, {
|
|
530
570
|
method: "POST",
|
|
@@ -556,6 +596,8 @@ function getRouteHandlers(args) {
|
|
|
556
596
|
return callbackGetHandler(req);
|
|
557
597
|
} else if (params.slug === "userinfo") {
|
|
558
598
|
return userinfoGetHandler(req);
|
|
599
|
+
} else if (params.slug === "logout") {
|
|
600
|
+
return logoutGetHandler(req);
|
|
559
601
|
} else {
|
|
560
602
|
return new Response("", { status: 404 });
|
|
561
603
|
}
|