Skip to content

Commit f6651e7

Browse files
committed
Add tests for middleware
1 parent cfdc2af commit f6651e7

File tree

4 files changed

+515
-37
lines changed

4 files changed

+515
-37
lines changed

lib/ts/nextjs/constants.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export const ACCESS_TOKEN_COOKIE_NAME = "sAccessToken";
2+
export const ACCESS_TOKEN_HEADER_NAME = "st-access-token";
3+
export const FRONT_TOKEN_COOKIE_NAME = "sFrontToken";
4+
export const FRONT_TOKEN_HEADER_NAME = "front-token";
5+
export const REFRESH_TOKEN_COOKIE_NAME = "sRefreshToken";
6+
export const REFRESH_TOKEN_HEADER_NAME = "st-refresh-token";
7+
export const ANTI_CSRF_TOKEN_COOKIE_NAME = "sAntiCsrf";
8+
export const ANTI_CSRF_TOKEN_HEADER_NAME = "anti-csrf";
9+
export const REDIRECT_ATTEMPT_MAX_COUNT = 5;
10+
export const REDIRECT_ATTEMPT_COUNT_COOKIE_NAME = "sSsrSessionRefreshAttempt";
11+
export const CURRENT_PATH_COOKIE_NAME = "sCurrentPath";
12+
export const FORCE_LOGOUT_PATH_PARAM_NAME = "forceLogout";
13+
export const REDIRECT_PATH_PARAM_NAME = "stRedirectTo";

lib/ts/nextjs/middleware.ts

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
import { enableLogging, logDebugMessage } from "../logger";
22

3-
import type { SuperTokensNextjsConfig } from "./types";
4-
5-
const ACCESS_TOKEN_COOKIE_NAME = "sAccessToken";
6-
const ACCESS_TOKEN_HEADER_NAME = "st-access-token";
7-
const FRONT_TOKEN_COOKIE_NAME = "sFrontToken";
8-
const FRONT_TOKEN_HEADER_NAME = "front-token";
9-
const REFRESH_TOKEN_COOKIE_NAME = "sRefreshToken";
10-
const REFRESH_TOKEN_HEADER_NAME = "st-refresh-token";
11-
const ANTI_CSRF_TOKEN_COOKIE_NAME = "sAntiCsrf";
12-
const ANTI_CSRF_TOKEN_HEADER_NAME = "anti-csrf";
3+
import {
4+
REDIRECT_ATTEMPT_MAX_COUNT,
5+
REFRESH_TOKEN_COOKIE_NAME,
6+
REFRESH_TOKEN_HEADER_NAME,
7+
REDIRECT_PATH_PARAM_NAME,
8+
REDIRECT_ATTEMPT_COUNT_COOKIE_NAME,
9+
ACCESS_TOKEN_COOKIE_NAME,
10+
ACCESS_TOKEN_HEADER_NAME,
11+
FRONT_TOKEN_HEADER_NAME,
12+
ANTI_CSRF_TOKEN_HEADER_NAME,
13+
FORCE_LOGOUT_PATH_PARAM_NAME,
14+
FRONT_TOKEN_COOKIE_NAME,
15+
ANTI_CSRF_TOKEN_COOKIE_NAME,
16+
} from "./constants";
1317

14-
const REDIRECT_ATTEMPT_MAX_COUNT = 5;
15-
const REDIRECT_PATH_PARAM_NAME = "stRedirectTo";
16-
const FORCE_LOGOUT_PATH_PARAM_NAME = "forceLogout";
17-
const REDIRECT_ATTEMPT_COUNT_COOKIE_NAME = "sSsrSessionRefreshAttempt";
18+
import type { SuperTokensNextjsConfig } from "./types";
1819

1920
let AppInfo: SuperTokensNextjsConfig["appInfo"];
2021

@@ -30,17 +31,15 @@ export async function refreshSession(config: SuperTokensNextjsConfig, request: R
3031
return redirectToAuthPage(request);
3132
}
3233

33-
const refreshToken =
34-
getCookie(request, REFRESH_TOKEN_COOKIE_NAME) || request.headers.get(REFRESH_TOKEN_HEADER_NAME);
35-
if (!refreshToken) {
34+
if (!getCookie(request, REFRESH_TOKEN_COOKIE_NAME) && !request.headers.get(REFRESH_TOKEN_HEADER_NAME)) {
3635
logDebugMessage("Refresh token not found");
3736
return redirectToAuthPage(request);
3837
}
3938

4039
const requestUrl = new URL(request.url);
4140
const redirectTo = requestUrl.searchParams.get(REDIRECT_PATH_PARAM_NAME) || "/";
4241
try {
43-
const tokens = await fetchNewTokens(refreshToken);
42+
const tokens = await fetchNewTokens(request);
4443
const hasRequiredCookies = tokens.accessToken && tokens.refreshToken && tokens.frontToken;
4544
if (!hasRequiredCookies) {
4645
logDebugMessage("Missing tokens from refresh response");
@@ -79,7 +78,6 @@ export async function revokeSession(config: SuperTokensNextjsConfig, request: Re
7978
if (config.enableDebugLogs) {
8079
enableLogging();
8180
}
82-
8381
const response = new Response(null, {});
8482

8583
try {
@@ -125,29 +123,36 @@ function redirectToAuthPage(request: Request): Response {
125123
});
126124
}
127125

128-
async function fetchNewTokens(currentRefreshToken: string): Promise<{
126+
async function fetchNewTokens(request: Request): Promise<{
129127
accessToken: string;
130128
refreshToken: string;
131129
frontToken: string;
132130
antiCsrfToken: string;
133131
}> {
134132
const refreshApiURL = new URL(`${AppInfo.apiBasePath}/session/refresh`, AppInfo.apiDomain);
133+
const cookieRefreshToken = getCookie(request, REFRESH_TOKEN_COOKIE_NAME);
134+
const headerRefreshToken = request.headers.get(REFRESH_TOKEN_HEADER_NAME);
135+
const refreshRequestHeaders: Record<string, string> = {
136+
"Content-Type": "application/json",
137+
};
138+
if (cookieRefreshToken) {
139+
refreshRequestHeaders.Cookie = `${REFRESH_TOKEN_COOKIE_NAME}=${cookieRefreshToken}`;
140+
} else if (headerRefreshToken) {
141+
refreshRequestHeaders[REFRESH_TOKEN_HEADER_NAME] = headerRefreshToken;
142+
}
143+
135144
const refreshResponse = await fetch(refreshApiURL, {
136145
method: "POST",
137-
headers: {
138-
"Content-Type": "application/json",
139-
[REFRESH_TOKEN_HEADER_NAME]: currentRefreshToken,
140-
Cookie: `${REFRESH_TOKEN_COOKIE_NAME}=${currentRefreshToken}`,
141-
},
146+
headers: refreshRequestHeaders,
142147
credentials: "include",
143148
});
144149
logDebugMessage("Session refresh request completed");
145-
150+
logDebugMessage("Session refresh request completed");
146151
const frontTokenHeaderValue = refreshResponse.headers.get(FRONT_TOKEN_HEADER_NAME);
147152
const cookieTokens = {
148153
accessToken: "",
149154
refreshToken: "",
150-
frontToken: `${FRONT_TOKEN_COOKIE_NAME}=${frontTokenHeaderValue}; HTTPOnly; Path=/`,
155+
frontToken: `${FRONT_TOKEN_COOKIE_NAME}=${frontTokenHeaderValue}; Path=/`,
151156
antiCsrfToken: "",
152157
};
153158
// TOOD: Review the current build target

lib/ts/nextjs/ssr.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@ import * as jose from "jose";
22

33
import { enableLogging, logDebugMessage } from "../logger";
44

5+
import {
6+
FRONT_TOKEN_HEADER_NAME,
7+
ACCESS_TOKEN_COOKIE_NAME,
8+
ACCESS_TOKEN_HEADER_NAME,
9+
CURRENT_PATH_COOKIE_NAME,
10+
FORCE_LOGOUT_PATH_PARAM_NAME,
11+
REDIRECT_PATH_PARAM_NAME,
12+
FRONT_TOKEN_COOKIE_NAME,
13+
} from "./constants";
514
import { isCookiesStore } from "./types";
615

716
import type { CookiesObject, CookiesStore, GetServerSidePropsReturnValue, SuperTokensNextjsConfig } from "./types";
817
import type { AccessTokenPayload, LoadedSessionContext } from "../recipe/session/types";
918

10-
const ACCESS_TOKEN_COOKIE_NAME = "sAccessToken";
11-
const ACCESS_TOKEN_HEADER_NAME = "st-access-token";
12-
const FRONT_TOKEN_NAME = "sFrontToken";
13-
const FRONT_TOKEN_HEADER_NAME = "front-token";
14-
15-
const CURRENT_PATH_COOKIE_NAME = "sCurrentPath";
16-
const FORCE_LOGOUT_PATH_PARAM_NAME = "forceLogout";
17-
const REDIRECT_PATH_PARAM_NAME = "stRedirectTo";
18-
1919
type SSRSessionState =
2020
| "front-token-not-found"
2121
| "front-token-invalid"
@@ -128,7 +128,8 @@ function getRefreshLocation(redirectPath: string): string {
128128
async function getSSRSessionState(
129129
cookies: CookiesObject | CookiesStore
130130
): Promise<{ state: SSRSessionState; session?: LoadedSessionContext }> {
131-
const frontToken = getCookieValue(cookies, FRONT_TOKEN_NAME) || getCookieValue(cookies, FRONT_TOKEN_HEADER_NAME);
131+
const frontToken =
132+
getCookieValue(cookies, FRONT_TOKEN_COOKIE_NAME) || getCookieValue(cookies, FRONT_TOKEN_HEADER_NAME);
132133
if (!frontToken) {
133134
return { state: "front-token-not-found" };
134135
}

0 commit comments

Comments
 (0)