@frontegg/nextjs 9.2.14-alpha.29367810197 → 9.2.14-alpha.34330679131
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/CHANGELOG.md +3 -1
- package/api/index.js +2 -1
- package/api/index.js.map +1 -1
- package/edge/getSessionOnEdge.js +3 -3
- package/edge/getSessionOnEdge.js.map +1 -1
- package/index.js +1 -1
- package/package.json +9 -2
- package/sdkVersion.js +1 -1
- package/sdkVersion.js.map +1 -1
- package/utils/refreshAccessTokenIfNeeded/helpers.d.ts +1 -1
- package/utils/refreshAccessTokenIfNeeded/helpers.js +5 -2
- package/utils/refreshAccessTokenIfNeeded/helpers.js.map +1 -1
- package/utils/routing/index.d.ts +24 -0
- package/utils/routing/index.js +56 -0
- package/utils/routing/index.js.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
## [9.2.14](https://github.com/frontegg/frontegg-nextjs/compare/v9.2.13...v9.2.14) (2026-
|
|
3
|
+
## [9.2.14](https://github.com/frontegg/frontegg-nextjs/compare/v9.2.13...v9.2.14) (2026-9-9)
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
### NextJS Wrapper 9.2.14:
|
|
7
|
+
- fix: honor authRoutes.hostedLoginRedirectUrl for hosted login callback
|
|
7
8
|
- fix: bump dependencies and resolve security vulnerabilities
|
|
9
|
+
- test: add unit + E2E test coverage for cookies and token refresh
|
|
8
10
|
|
|
9
11
|
## [9.2.13](https://github.com/frontegg/frontegg-nextjs/compare/v9.2.12...v9.2.13) (2026-3-4)
|
|
10
12
|
|
package/api/index.js
CHANGED
|
@@ -9,6 +9,7 @@ var _config = _interopRequireDefault(require("../config"));
|
|
|
9
9
|
var _utils = require("./utils");
|
|
10
10
|
var _restApi = require("@frontegg/rest-api");
|
|
11
11
|
var _urls = require("../utils/common/urls");
|
|
12
|
+
var _routing = require("../utils/routing");
|
|
12
13
|
/**
|
|
13
14
|
* Send HTTP GET to frontegg domain public route to download the JWT public key
|
|
14
15
|
*/
|
|
@@ -57,7 +58,7 @@ const exchangeHostedLoginToken = async (headers, code, cliendId, clientSecret) =
|
|
|
57
58
|
return (0, _utils.Post)({
|
|
58
59
|
url: `${_config.default.baseUrl}${_urls.CommonUrls.refreshToken.hosted}`,
|
|
59
60
|
body: JSON.stringify({
|
|
60
|
-
redirect_uri:
|
|
61
|
+
redirect_uri: (0, _routing.buildHostedLoginRedirectUri)(),
|
|
61
62
|
grant_type: 'authorization_code',
|
|
62
63
|
code,
|
|
63
64
|
client_id: cliendId,
|
package/api/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_config","_interopRequireDefault","require","_utils","_restApi","_urls","loadPublicKey","response","fetch","config","baseUrl","CommonUrls","WellKnown","jwks","cache","data","json","keys","refreshTokenEmbedded","headers","Post","url","refreshToken","embedded","body","credentials","buildRequestHeaders","refreshTokenHostedLogin","clientId","clientSecret","hosted","JSON","stringify","grant_type","refresh_token","client_id","client_secret","exchangeHostedLoginToken","code","cliendId","redirect_uri","
|
|
1
|
+
{"version":3,"file":"index.js","names":["_config","_interopRequireDefault","require","_utils","_restApi","_urls","_routing","loadPublicKey","response","fetch","config","baseUrl","CommonUrls","WellKnown","jwks","cache","data","json","keys","refreshTokenEmbedded","headers","Post","url","refreshToken","embedded","body","credentials","buildRequestHeaders","refreshTokenHostedLogin","clientId","clientSecret","hosted","JSON","stringify","grant_type","refresh_token","client_id","client_secret","exchangeHostedLoginToken","code","cliendId","redirect_uri","buildHostedLoginRedirectUri","exports","getMe","headersToSend","res","Get","fronteggUsersUrl","parseHttpResponse","getEntitlements","fronteggEntitlementsV2Url","getTenants","fronteggTenantsV3Url","getMeAuthorization","getPublicSettings","_default","default"],"sources":["../../../../packages/nextjs/src/api/index.ts"],"sourcesContent":["import config from '../config';\nimport { buildRequestHeaders, Get, parseHttpResponse, Post } from './utils';\nimport {\n fronteggTenantsV3Url,\n fronteggUsersUrl,\n ILoginResponse,\n GetCurrentUserTenantsResponse,\n IPublicSettingsResponse,\n IGetUserAuthorizationResponse,\n fronteggEntitlementsV2Url,\n} from '@frontegg/rest-api';\n\nimport { UserEntitlementsResponseV2 } from '@frontegg/types';\nimport { CommonUrls } from '../utils/common/urls';\nimport { buildHostedLoginRedirectUri } from '../utils/routing';\n\n/**\n * Send HTTP GET to frontegg domain public route to download the JWT public key\n */\nconst loadPublicKey = async () => {\n const response = await fetch(`${config.baseUrl}${CommonUrls.WellKnown.jwks}`, {\n cache: 'force-cache',\n });\n const data = await response.json();\n return data.keys[0];\n};\n\n/**\n * Send HTTP post-request for Frontegg services to refresh token\n * by providing client's fe_ cookies\n */\nconst refreshTokenEmbedded = async (headers: Record<string, string>) => {\n return Post({\n url: `${config.baseUrl}${CommonUrls.refreshToken.embedded}`,\n body: '{}',\n credentials: 'include',\n headers: buildRequestHeaders(headers),\n });\n};\n\n/**\n * Send HTTP post request for Frontegg services to refresh `hosted login` token\n * by providing client's fe_ as body with grant_type.\n */\nconst refreshTokenHostedLogin = async (\n headers: Record<string, string>,\n refreshToken: string,\n clientId?: string,\n clientSecret?: string\n) => {\n return Post({\n url: `${config.baseUrl}${CommonUrls.refreshToken.hosted}`,\n body: JSON.stringify({\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: clientId,\n client_secret: clientSecret,\n }),\n headers: buildRequestHeaders(headers),\n });\n};\n\n/**\n * Send HTTP post request for Frontegg services to exchange `hosted login` callback code\n */\nexport const exchangeHostedLoginToken = async (\n headers: Record<string, string>,\n code: string,\n cliendId: string,\n clientSecret: string\n) => {\n return Post({\n url: `${config.baseUrl}${CommonUrls.refreshToken.hosted}`,\n body: JSON.stringify({\n redirect_uri: buildHostedLoginRedirectUri(),\n grant_type: 'authorization_code',\n code,\n client_id: cliendId,\n client_secret: clientSecret,\n // code_verifier\n }),\n headers: buildRequestHeaders(headers),\n });\n};\n\n/**\n *\n * @param headers\n */\nexport const getMe = async (headers: Record<string, string>): Promise<ILoginResponse | undefined> => {\n const headersToSend = buildRequestHeaders(headers);\n const res = await Get({\n url: `${config.baseUrl}/frontegg${fronteggUsersUrl}`,\n headers: headersToSend,\n });\n return parseHttpResponse(res);\n};\n\n/**\n *\n * @param headers\n */\nexport const getEntitlements = async (\n headers: Record<string, string>\n): Promise<UserEntitlementsResponseV2 | undefined> => {\n const headersToSend = buildRequestHeaders(headers);\n const res = await Get({\n url: `${config.baseUrl}${fronteggEntitlementsV2Url}`,\n headers: headersToSend,\n });\n return parseHttpResponse(res);\n};\n\n/**\n *\n * @param headers\n */\nexport const getTenants = async (\n headers: Record<string, string>\n): Promise<GetCurrentUserTenantsResponse | undefined> => {\n const res = await Get({\n url: `${config.baseUrl}/frontegg${fronteggTenantsV3Url}`,\n headers: buildRequestHeaders(headers),\n });\n return parseHttpResponse(res);\n};\n\n/**\n *\n * @param headers\n */\nexport const getMeAuthorization = async (\n headers: Record<string, string>\n): Promise<IGetUserAuthorizationResponse | undefined> => {\n const res = await Get({\n // TODO: replace this with rest/api route\n url: `${config.baseUrl}/frontegg/identity/resources/users/v1/me/authorization`,\n headers: buildRequestHeaders(headers),\n });\n return parseHttpResponse(res);\n};\n\nexport const getPublicSettings = async (\n headers: Record<string, string>\n): Promise<IPublicSettingsResponse | undefined> => {\n const res = await Get({\n // TODO: export the route url from rest-api and import from there\n url: `${config.baseUrl}/frontegg/tenants/resources/account-settings/v1/public`,\n headers: buildRequestHeaders(headers),\n });\n return parseHttpResponse(res);\n};\n\nexport default {\n loadPublicKey,\n refreshTokenEmbedded,\n refreshTokenHostedLogin,\n getMe,\n getTenants,\n getPublicSettings,\n getEntitlements,\n exchangeHostedLoginToken,\n};\n"],"mappings":"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","ignoreList":[]}
|
package/edge/getSessionOnEdge.js
CHANGED
|
@@ -18,6 +18,7 @@ var _fronteggLogger = _interopRequireDefault(require("../utils/fronteggLogger"))
|
|
|
18
18
|
var _refreshAccessTokenIfNeededOnEdge = require("./refreshAccessTokenIfNeededOnEdge");
|
|
19
19
|
var _redirectToLogin = require("./redirectToLogin");
|
|
20
20
|
var _shouldBypassMiddleware = require("./shouldBypassMiddleware");
|
|
21
|
+
var _routing = require("../utils/routing");
|
|
21
22
|
const logger = _fronteggLogger.default.child({
|
|
22
23
|
tag: 'EdgeRuntime.getSessionOnEdge'
|
|
23
24
|
});
|
|
@@ -238,9 +239,8 @@ const handleHostedLoginCallback = async (req, pathname, searchParams) => {
|
|
|
238
239
|
exports.handleHostedLoginCallback = handleHostedLoginCallback;
|
|
239
240
|
const isHostedLoginCallback = (pathname, searchParams) => {
|
|
240
241
|
if (_config.default.secureJwtEnabled) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
242
|
+
const hasCode = searchParams.get('code') != null;
|
|
243
|
+
return hasCode && (0, _routing.isHostedLoginCallbackPath)(pathname, hasCode);
|
|
244
244
|
}
|
|
245
245
|
return false;
|
|
246
246
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getSessionOnEdge.js","names":["_cookies","_interopRequireDefault","require","_createSession","_encryptionEdge","_api","_server","_config","_jwt","_utils","_fronteggLogger","_refreshAccessTokenIfNeededOnEdge","_redirectToLogin","_shouldBypassMiddleware","logger","fronteggLogger","child","tag","handleSessionOnEdge","params","request","pathname","searchParams","headers","isHostedLoginCallback","handleHostedLoginCallback","shouldByPassMiddleware","NextResponse","next","edgeSession","checkSessionOnEdge","redirectToLogin","forwardedHeaders","exports","GET_SESSION_ON_EDGE_DEPRECATED_WARN","getSessionOnEdge","req","disableWarning","cookies","CookieManager","getSessionCookieFromRequest","info","createSession","encryptionEdge","sessionCookies","existingSession","debug","session","refreshAccessTokenIfNeededOnEdge","createSessionFromAccessTokenEdge","data","_data$accessToken","_data$refreshToken","accessToken","access_token","refreshToken","refresh_token","payload","decodedJwt","JwtManager","verify","expiresIn","Math","floor","exp","Date","now","tokens","sealTokens","_searchParams$get","_req$headers","code","get","clientIp","undefined","_socket","getClientIp","socket","remoteAddress","_socket2","requestHeaders","_extends2","default","config","shouldForwardIp","_config$sharedSecret","FRONTEGG_FORWARD_IP_HEADER","FRONTEGG_HEADERS_VERIFIER_HEADER","sharedSecret","FRONTEGG_VENDOR_ID_HEADER","clientId","response","api","exchangeHostedLoginToken","buildRequestHeaders","clientSecret","json","redirect","appUrl","isSecured","isSSL","cookieValue","create","value","expires","secure","cookieName","replace","rewriteCookieByAppId","appId","refreshCookie","sessionCookieHeaders","map","cookie","refreshCookieHeaders","secureJwtEnabled","startsWith"],"sources":["../../../../packages/nextjs/src/edge/getSessionOnEdge.ts"],"sourcesContent":["import type { IncomingMessage } from 'http';\nimport { FronteggEdgeSession, FronteggNextJSSession } from '../types';\nimport CookieManager from '../utils/cookies';\nimport createSession from '../utils/createSession';\nimport encryptionEdge from '../utils/encryption-edge';\nimport api from '../api';\nimport { type NextRequest, NextResponse } from 'next/server';\nimport config from '../config';\nimport JwtManager from '../utils/jwt';\nimport {\n buildRequestHeaders,\n FRONTEGG_HEADERS_VERIFIER_HEADER,\n FRONTEGG_FORWARD_IP_HEADER,\n getClientIp,\n FRONTEGG_VENDOR_ID_HEADER,\n} from '../api/utils';\nimport fronteggLogger from '../utils/fronteggLogger';\nimport { refreshAccessTokenIfNeededOnEdge } from './refreshAccessTokenIfNeededOnEdge';\nimport { redirectToLogin } from './redirectToLogin';\nimport { shouldByPassMiddleware } from './shouldBypassMiddleware';\n\nconst logger = fronteggLogger.child({ tag: 'EdgeRuntime.getSessionOnEdge' });\n\nexport type HandleSessionOnEdge = {\n request: IncomingMessage | Request;\n pathname: string;\n headers: NextRequest['headers'];\n searchParams: URLSearchParams;\n};\n\nexport const handleSessionOnEdge = async (params: HandleSessionOnEdge): Promise<NextResponse> => {\n const { request, pathname, searchParams, headers } = params;\n\n if (isHostedLoginCallback(pathname, searchParams)) {\n return handleHostedLoginCallback(request, pathname, searchParams);\n }\n\n if (shouldByPassMiddleware(pathname, headers /*, options: optional bypass configuration */)) {\n return NextResponse.next();\n }\n\n const edgeSession = await checkSessionOnEdge(request);\n if (!edgeSession) {\n return redirectToLogin(pathname, searchParams);\n }\n if (edgeSession.headers) {\n return NextResponse.next({\n headers: edgeSession.headers,\n request: {\n headers: edgeSession.forwardedHeaders,\n },\n });\n }\n return NextResponse.next();\n};\n\nconst GET_SESSION_ON_EDGE_DEPRECATED_WARN = `Deprecation Notice: getSessionOnEdge has been deprecated. Please use handleSessionOnEdge instead. For example:\n\nfile: middleware.ts\n\\`\\`\\`ts\n import { NextRequest } from 'next/server';\n import { handleSessionOnEdge } from '@frontegg/nextjs/edge';\n \n export const middleware = async (request: NextRequest) => {\n const { pathname, searchParams } = request.nextUrl;\n const headers = request.headers;\n \n // Additional logic if needed\n \n return handleSessionOnEdge({ request, pathname, searchParams, headers });\n };\n \n \n export const config = {\n matcher: '/(.*)',\n };\n\n\\`\\`\\`\n\nAlternatively, to manually verify the session, you can use checkSessionOnEdge. Note that this method does not redirect to the login page if the session is invalid.\n`;\n\n/**\n * getSessionOnEdge is deprecated, please use handleSessionOnEdge instead example:\n *\n * ```ts\n * import { NextRequest } from 'next/server';\n * import { handleSessionOnEdge } from '@frontegg/nextjs/edge';\n *\n * export const middleware = async (request: NextRequest) => {\n * const { pathname, searchParams } = request.nextUrl;\n * const headers = request.headers;\n *\n * // Additional logic if needed\n *\n * return handleSessionOnEdge({ request, pathname, searchParams, headers });\n * };\n *\n * export const config = {\n * matcher: '/(.*)',\n * };\n * ```\n * @deprecated\n */\n\nexport const getSessionOnEdge = (\n req: IncomingMessage | Request,\n disableWarning = false\n): Promise<FronteggNextJSSession | undefined> => {\n const logger = fronteggLogger.child({ tag: 'EdgeRuntime.getSessionOnEdge' });\n const cookies = CookieManager.getSessionCookieFromRequest(req);\n if (!disableWarning) {\n logger.info(GET_SESSION_ON_EDGE_DEPRECATED_WARN);\n }\n return createSession(cookies, encryptionEdge);\n};\n\n/**\n * Check session on edge and return session if exists this method does not redirect to login page\n * Example:\n *\n * ```ts\n * import { NextRequest } from 'next/server';\n * import { handleSessionOnEdge } from '@frontegg/nextjs/edge';\n *\n * export const middleware = async (request: NextRequest) => {\n * const { pathname, searchParams } = request.nextUrl;\n * const headers = request.headers;\n *\n * // Additional logic if needed\n *\n * // check if it's a hosted login callback\n * if (isHostedLoginCallback(pathname, searchParams)) {\n * return handleHostedLoginCallback(request, pathname, searchParams);\n * }\n *\n * // check if we should bypass the middleware\n * if (shouldByPassMiddleware(pathname)) {\n * return NextResponse.next();\n * }\n *\n * // check session\n * const session = await checkSessionOnEdge(request);\n *\n * if (!session) {\n * return redirectToLogin(pathname);\n * }\n *\n * // if headers are present forward them to the next response / request\n * if (session.headers) {\n * return NextResponse.next({\n * headers: edgeSession.headers,\n * request:{\n * headers: edgeSession.forwardedHeaders\n * }\n * });\n * }\n * return NextResponse.next();\n * };\n * ```\n *\n *\n * @param req\n */\nexport const checkSessionOnEdge = async (req: IncomingMessage | Request): Promise<FronteggEdgeSession | undefined> => {\n const sessionCookies = CookieManager.getSessionCookieFromRequest(req);\n let existingSession = await createSession(sessionCookies, encryptionEdge);\n if (existingSession) {\n logger.debug('session resolved from session cookie');\n return {\n session: existingSession,\n };\n }\n\n logger.debug('Failed to resolve session from cookie, going to refresh token');\n return refreshAccessTokenIfNeededOnEdge(req);\n};\n\nasync function createSessionFromAccessTokenEdge(data: any): Promise<[string, any, string] | []> {\n const accessToken = data.accessToken ?? data.access_token;\n const refreshToken = data.refreshToken ?? data.refresh_token;\n const { payload: decodedJwt }: any = await JwtManager.verify(accessToken);\n decodedJwt.expiresIn = Math.floor((decodedJwt.exp * 1000 - Date.now()) / 1000);\n\n const tokens = { accessToken, refreshToken };\n const session = await encryptionEdge.sealTokens(tokens, decodedJwt.exp);\n return [session, decodedJwt, refreshToken];\n}\n\nexport const handleHostedLoginCallback = async (\n req: IncomingMessage | Request,\n pathname: string,\n searchParams: URLSearchParams\n): Promise<NextResponse> => {\n if (!isHostedLoginCallback(pathname, searchParams)) {\n return NextResponse.next();\n }\n\n const code = searchParams.get('code') ?? '';\n\n let headers: Record<string, string> = {};\n let clientIp: string | undefined = undefined;\n if (typeof req.headers?.get === 'function') {\n clientIp =\n getClientIp(req.headers.get('cf-connecting-ip') || req.headers.get('x-forwarded-for')) ||\n (req as any).socket?.remoteAddress;\n } else if (typeof req.headers === 'object') {\n let requestHeaders: any = { ...req.headers };\n clientIp =\n getClientIp(requestHeaders['cf-connecting-ip'] || requestHeaders['x-forwarded-for']) ||\n (req as any).socket?.remoteAddress;\n }\n\n if (clientIp && config.shouldForwardIp) {\n headers[FRONTEGG_FORWARD_IP_HEADER] = clientIp;\n headers[FRONTEGG_HEADERS_VERIFIER_HEADER] = config.sharedSecret ?? '';\n headers[FRONTEGG_VENDOR_ID_HEADER] = config.clientId;\n }\n\n const response = await api.exchangeHostedLoginToken(\n buildRequestHeaders(headers),\n code,\n config.clientId,\n config.clientSecret!\n );\n\n const data = await response.json();\n\n const [session, decodedJwt, refreshToken] = await createSessionFromAccessTokenEdge(data);\n\n if (!session) {\n return NextResponse.redirect(config.appUrl);\n }\n const isSecured = config.isSSL;\n const cookieValue = CookieManager.create({\n value: session,\n expires: new Date(decodedJwt.exp * 1000),\n secure: isSecured,\n });\n\n let cookieName = `fe_refresh_${config.clientId.replace('-', '')}`;\n if (config.rewriteCookieByAppId && config.appId) {\n cookieName = `fe_refresh_${config.appId.replace('-', '')}`;\n }\n const refreshCookie = CookieManager.create({\n cookieName,\n value: refreshToken ?? '',\n expires: new Date(decodedJwt.exp * 1000),\n secure: isSecured,\n });\n const sessionCookieHeaders: [string, string][] = cookieValue.map((cookie) => ['set-cookie', cookie]);\n const refreshCookieHeaders: [string, string][] = refreshCookie.map((cookie) => ['set-cookie', cookie]);\n\n return NextResponse.redirect(config.appUrl, {\n headers: [...sessionCookieHeaders, ...refreshCookieHeaders],\n });\n};\n\nexport const isHostedLoginCallback = (pathname: string, searchParams: URLSearchParams): boolean => {\n if (config.secureJwtEnabled) {\n if (pathname.startsWith('/oauth/callback')) {\n return searchParams.get('code') != null;\n }\n }\n return false;\n};\n"],"mappings":";;;;;;;;AAEA,IAAAA,QAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,cAAA,GAAAF,sBAAA,CAAAC,OAAA;AACA,IAAAE,eAAA,GAAAH,sBAAA,CAAAC,OAAA;AACA,IAAAG,IAAA,GAAAJ,sBAAA,CAAAC,OAAA;AACA,IAAAI,OAAA,GAAAJ,OAAA;AACA,IAAAK,OAAA,GAAAN,sBAAA,CAAAC,OAAA;AACA,IAAAM,IAAA,GAAAP,sBAAA,CAAAC,OAAA;AACA,IAAAO,MAAA,GAAAP,OAAA;AAOA,IAAAQ,eAAA,GAAAT,sBAAA,CAAAC,OAAA;AACA,IAAAS,iCAAA,GAAAT,OAAA;AACA,IAAAU,gBAAA,GAAAV,OAAA;AACA,IAAAW,uBAAA,GAAAX,OAAA;AAEA,MAAMY,MAAM,GAAGC,uBAAc,CAACC,KAAK,CAAC;EAAEC,GAAG,EAAE;AAA+B,CAAC,CAAC;AASrE,MAAMC,mBAAmB,GAAG,MAAOC,MAA2B,IAA4B;EAC/F,MAAM;IAAEC,OAAO;IAAEC,QAAQ;IAAEC,YAAY;IAAEC;EAAQ,CAAC,GAAGJ,MAAM;EAE3D,IAAIK,qBAAqB,CAACH,QAAQ,EAAEC,YAAY,CAAC,EAAE;IACjD,OAAOG,yBAAyB,CAACL,OAAO,EAAEC,QAAQ,EAAEC,YAAY,CAAC;EACnE;EAEA,IAAI,IAAAI,8CAAsB,EAACL,QAAQ,EAAEE,OAAO,CAAC,6CAA6C,CAAC,EAAE;IAC3F,OAAOI,oBAAY,CAACC,IAAI,CAAC,CAAC;EAC5B;EAEA,MAAMC,WAAW,GAAG,MAAMC,kBAAkB,CAACV,OAAO,CAAC;EACrD,IAAI,CAACS,WAAW,EAAE;IAChB,OAAO,IAAAE,gCAAe,EAACV,QAAQ,EAAEC,YAAY,CAAC;EAChD;EACA,IAAIO,WAAW,CAACN,OAAO,EAAE;IACvB,OAAOI,oBAAY,CAACC,IAAI,CAAC;MACvBL,OAAO,EAAEM,WAAW,CAACN,OAAO;MAC5BH,OAAO,EAAE;QACPG,OAAO,EAAEM,WAAW,CAACG;MACvB;IACF,CAAC,CAAC;EACJ;EACA,OAAOL,oBAAY,CAACC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAACK,OAAA,CAAAf,mBAAA,GAAAA,mBAAA;AAEF,MAAMgB,mCAAmC,GAAG;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEO,MAAMC,gBAAgB,GAAGA,CAC9BC,GAA8B,EAC9BC,cAAc,GAAG,KAAK,KACyB;EAC/C,MAAMvB,MAAM,GAAGC,uBAAc,CAACC,KAAK,CAAC;IAAEC,GAAG,EAAE;EAA+B,CAAC,CAAC;EAC5E,MAAMqB,OAAO,GAAGC,gBAAa,CAACC,2BAA2B,CAACJ,GAAG,CAAC;EAC9D,IAAI,CAACC,cAAc,EAAE;IACnBvB,MAAM,CAAC2B,IAAI,CAACP,mCAAmC,CAAC;EAClD;EACA,OAAO,IAAAQ,sBAAa,EAACJ,OAAO,EAAEK,uBAAc,CAAC;AAC/C,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AA9CAV,OAAA,CAAAE,gBAAA,GAAAA,gBAAA;AA+CO,MAAML,kBAAkB,GAAG,MAAOM,GAA8B,IAA+C;EACpH,MAAMQ,cAAc,GAAGL,gBAAa,CAACC,2BAA2B,CAACJ,GAAG,CAAC;EACrE,IAAIS,eAAe,GAAG,MAAM,IAAAH,sBAAa,EAACE,cAAc,EAAED,uBAAc,CAAC;EACzE,IAAIE,eAAe,EAAE;IACnB/B,MAAM,CAACgC,KAAK,CAAC,sCAAsC,CAAC;IACpD,OAAO;MACLC,OAAO,EAAEF;IACX,CAAC;EACH;EAEA/B,MAAM,CAACgC,KAAK,CAAC,+D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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"getSessionOnEdge.js","names":["_cookies","_interopRequireDefault","require","_createSession","_encryptionEdge","_api","_server","_config","_jwt","_utils","_fronteggLogger","_refreshAccessTokenIfNeededOnEdge","_redirectToLogin","_shouldBypassMiddleware","_routing","logger","fronteggLogger","child","tag","handleSessionOnEdge","params","request","pathname","searchParams","headers","isHostedLoginCallback","handleHostedLoginCallback","shouldByPassMiddleware","NextResponse","next","edgeSession","checkSessionOnEdge","redirectToLogin","forwardedHeaders","exports","GET_SESSION_ON_EDGE_DEPRECATED_WARN","getSessionOnEdge","req","disableWarning","cookies","CookieManager","getSessionCookieFromRequest","info","createSession","encryptionEdge","sessionCookies","existingSession","debug","session","refreshAccessTokenIfNeededOnEdge","createSessionFromAccessTokenEdge","data","_data$accessToken","_data$refreshToken","accessToken","access_token","refreshToken","refresh_token","payload","decodedJwt","JwtManager","verify","expiresIn","Math","floor","exp","Date","now","tokens","sealTokens","_searchParams$get","_req$headers","code","get","clientIp","undefined","_socket","getClientIp","socket","remoteAddress","_socket2","requestHeaders","_extends2","default","config","shouldForwardIp","_config$sharedSecret","FRONTEGG_FORWARD_IP_HEADER","FRONTEGG_HEADERS_VERIFIER_HEADER","sharedSecret","FRONTEGG_VENDOR_ID_HEADER","clientId","response","api","exchangeHostedLoginToken","buildRequestHeaders","clientSecret","json","redirect","appUrl","isSecured","isSSL","cookieValue","create","value","expires","secure","cookieName","replace","rewriteCookieByAppId","appId","refreshCookie","sessionCookieHeaders","map","cookie","refreshCookieHeaders","secureJwtEnabled","hasCode","isHostedLoginCallbackPath"],"sources":["../../../../packages/nextjs/src/edge/getSessionOnEdge.ts"],"sourcesContent":["import type { IncomingMessage } from 'http';\nimport { FronteggEdgeSession, FronteggNextJSSession } from '../types';\nimport CookieManager from '../utils/cookies';\nimport createSession from '../utils/createSession';\nimport encryptionEdge from '../utils/encryption-edge';\nimport api from '../api';\nimport { type NextRequest, NextResponse } from 'next/server';\nimport config from '../config';\nimport JwtManager from '../utils/jwt';\nimport {\n buildRequestHeaders,\n FRONTEGG_HEADERS_VERIFIER_HEADER,\n FRONTEGG_FORWARD_IP_HEADER,\n getClientIp,\n FRONTEGG_VENDOR_ID_HEADER,\n} from '../api/utils';\nimport fronteggLogger from '../utils/fronteggLogger';\nimport { refreshAccessTokenIfNeededOnEdge } from './refreshAccessTokenIfNeededOnEdge';\nimport { redirectToLogin } from './redirectToLogin';\nimport { shouldByPassMiddleware } from './shouldBypassMiddleware';\nimport { isHostedLoginCallbackPath } from '../utils/routing';\n\nconst logger = fronteggLogger.child({ tag: 'EdgeRuntime.getSessionOnEdge' });\n\nexport type HandleSessionOnEdge = {\n request: IncomingMessage | Request;\n pathname: string;\n headers: NextRequest['headers'];\n searchParams: URLSearchParams;\n};\n\nexport const handleSessionOnEdge = async (params: HandleSessionOnEdge): Promise<NextResponse> => {\n const { request, pathname, searchParams, headers } = params;\n\n if (isHostedLoginCallback(pathname, searchParams)) {\n return handleHostedLoginCallback(request, pathname, searchParams);\n }\n\n if (shouldByPassMiddleware(pathname, headers /*, options: optional bypass configuration */)) {\n return NextResponse.next();\n }\n\n const edgeSession = await checkSessionOnEdge(request);\n if (!edgeSession) {\n return redirectToLogin(pathname, searchParams);\n }\n if (edgeSession.headers) {\n return NextResponse.next({\n headers: edgeSession.headers,\n request: {\n headers: edgeSession.forwardedHeaders,\n },\n });\n }\n return NextResponse.next();\n};\n\nconst GET_SESSION_ON_EDGE_DEPRECATED_WARN = `Deprecation Notice: getSessionOnEdge has been deprecated. Please use handleSessionOnEdge instead. For example:\n\nfile: middleware.ts\n\\`\\`\\`ts\n import { NextRequest } from 'next/server';\n import { handleSessionOnEdge } from '@frontegg/nextjs/edge';\n \n export const middleware = async (request: NextRequest) => {\n const { pathname, searchParams } = request.nextUrl;\n const headers = request.headers;\n \n // Additional logic if needed\n \n return handleSessionOnEdge({ request, pathname, searchParams, headers });\n };\n \n \n export const config = {\n matcher: '/(.*)',\n };\n\n\\`\\`\\`\n\nAlternatively, to manually verify the session, you can use checkSessionOnEdge. Note that this method does not redirect to the login page if the session is invalid.\n`;\n\n/**\n * getSessionOnEdge is deprecated, please use handleSessionOnEdge instead example:\n *\n * ```ts\n * import { NextRequest } from 'next/server';\n * import { handleSessionOnEdge } from '@frontegg/nextjs/edge';\n *\n * export const middleware = async (request: NextRequest) => {\n * const { pathname, searchParams } = request.nextUrl;\n * const headers = request.headers;\n *\n * // Additional logic if needed\n *\n * return handleSessionOnEdge({ request, pathname, searchParams, headers });\n * };\n *\n * export const config = {\n * matcher: '/(.*)',\n * };\n * ```\n * @deprecated\n */\n\nexport const getSessionOnEdge = (\n req: IncomingMessage | Request,\n disableWarning = false\n): Promise<FronteggNextJSSession | undefined> => {\n const logger = fronteggLogger.child({ tag: 'EdgeRuntime.getSessionOnEdge' });\n const cookies = CookieManager.getSessionCookieFromRequest(req);\n if (!disableWarning) {\n logger.info(GET_SESSION_ON_EDGE_DEPRECATED_WARN);\n }\n return createSession(cookies, encryptionEdge);\n};\n\n/**\n * Check session on edge and return session if exists this method does not redirect to login page\n * Example:\n *\n * ```ts\n * import { NextRequest } from 'next/server';\n * import { handleSessionOnEdge } from '@frontegg/nextjs/edge';\n *\n * export const middleware = async (request: NextRequest) => {\n * const { pathname, searchParams } = request.nextUrl;\n * const headers = request.headers;\n *\n * // Additional logic if needed\n *\n * // check if it's a hosted login callback\n * if (isHostedLoginCallback(pathname, searchParams)) {\n * return handleHostedLoginCallback(request, pathname, searchParams);\n * }\n *\n * // check if we should bypass the middleware\n * if (shouldByPassMiddleware(pathname)) {\n * return NextResponse.next();\n * }\n *\n * // check session\n * const session = await checkSessionOnEdge(request);\n *\n * if (!session) {\n * return redirectToLogin(pathname);\n * }\n *\n * // if headers are present forward them to the next response / request\n * if (session.headers) {\n * return NextResponse.next({\n * headers: edgeSession.headers,\n * request:{\n * headers: edgeSession.forwardedHeaders\n * }\n * });\n * }\n * return NextResponse.next();\n * };\n * ```\n *\n *\n * @param req\n */\nexport const checkSessionOnEdge = async (req: IncomingMessage | Request): Promise<FronteggEdgeSession | undefined> => {\n const sessionCookies = CookieManager.getSessionCookieFromRequest(req);\n let existingSession = await createSession(sessionCookies, encryptionEdge);\n if (existingSession) {\n logger.debug('session resolved from session cookie');\n return {\n session: existingSession,\n };\n }\n\n logger.debug('Failed to resolve session from cookie, going to refresh token');\n return refreshAccessTokenIfNeededOnEdge(req);\n};\n\nasync function createSessionFromAccessTokenEdge(data: any): Promise<[string, any, string] | []> {\n const accessToken = data.accessToken ?? data.access_token;\n const refreshToken = data.refreshToken ?? data.refresh_token;\n const { payload: decodedJwt }: any = await JwtManager.verify(accessToken);\n decodedJwt.expiresIn = Math.floor((decodedJwt.exp * 1000 - Date.now()) / 1000);\n\n const tokens = { accessToken, refreshToken };\n const session = await encryptionEdge.sealTokens(tokens, decodedJwt.exp);\n return [session, decodedJwt, refreshToken];\n}\n\nexport const handleHostedLoginCallback = async (\n req: IncomingMessage | Request,\n pathname: string,\n searchParams: URLSearchParams\n): Promise<NextResponse> => {\n if (!isHostedLoginCallback(pathname, searchParams)) {\n return NextResponse.next();\n }\n\n const code = searchParams.get('code') ?? '';\n\n let headers: Record<string, string> = {};\n let clientIp: string | undefined = undefined;\n if (typeof req.headers?.get === 'function') {\n clientIp =\n getClientIp(req.headers.get('cf-connecting-ip') || req.headers.get('x-forwarded-for')) ||\n (req as any).socket?.remoteAddress;\n } else if (typeof req.headers === 'object') {\n let requestHeaders: any = { ...req.headers };\n clientIp =\n getClientIp(requestHeaders['cf-connecting-ip'] || requestHeaders['x-forwarded-for']) ||\n (req as any).socket?.remoteAddress;\n }\n\n if (clientIp && config.shouldForwardIp) {\n headers[FRONTEGG_FORWARD_IP_HEADER] = clientIp;\n headers[FRONTEGG_HEADERS_VERIFIER_HEADER] = config.sharedSecret ?? '';\n headers[FRONTEGG_VENDOR_ID_HEADER] = config.clientId;\n }\n\n const response = await api.exchangeHostedLoginToken(\n buildRequestHeaders(headers),\n code,\n config.clientId,\n config.clientSecret!\n );\n\n const data = await response.json();\n\n const [session, decodedJwt, refreshToken] = await createSessionFromAccessTokenEdge(data);\n\n if (!session) {\n return NextResponse.redirect(config.appUrl);\n }\n const isSecured = config.isSSL;\n const cookieValue = CookieManager.create({\n value: session,\n expires: new Date(decodedJwt.exp * 1000),\n secure: isSecured,\n });\n\n let cookieName = `fe_refresh_${config.clientId.replace('-', '')}`;\n if (config.rewriteCookieByAppId && config.appId) {\n cookieName = `fe_refresh_${config.appId.replace('-', '')}`;\n }\n const refreshCookie = CookieManager.create({\n cookieName,\n value: refreshToken ?? '',\n expires: new Date(decodedJwt.exp * 1000),\n secure: isSecured,\n });\n const sessionCookieHeaders: [string, string][] = cookieValue.map((cookie) => ['set-cookie', cookie]);\n const refreshCookieHeaders: [string, string][] = refreshCookie.map((cookie) => ['set-cookie', cookie]);\n\n return NextResponse.redirect(config.appUrl, {\n headers: [...sessionCookieHeaders, ...refreshCookieHeaders],\n });\n};\n\nexport const isHostedLoginCallback = (pathname: string, searchParams: URLSearchParams): boolean => {\n if (config.secureJwtEnabled) {\n const hasCode = searchParams.get('code') != null;\n return hasCode && isHostedLoginCallbackPath(pathname, hasCode);\n }\n return false;\n};\n"],"mappings":";;;;;;;;AAEA,IAAAA,QAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,cAAA,GAAAF,sBAAA,CAAAC,OAAA;AACA,IAAAE,eAAA,GAAAH,sBAAA,CAAAC,OAAA;AACA,IAAAG,IAAA,GAAAJ,sBAAA,CAAAC,OAAA;AACA,IAAAI,OAAA,GAAAJ,OAAA;AACA,IAAAK,OAAA,GAAAN,sBAAA,CAAAC,OAAA;AACA,IAAAM,IAAA,GAAAP,sBAAA,CAAAC,OAAA;AACA,IAAAO,MAAA,GAAAP,OAAA;AAOA,IAAAQ,eAAA,GAAAT,sBAAA,CAAAC,OAAA;AACA,IAAAS,iCAAA,GAAAT,OAAA;AACA,IAAAU,gBAAA,GAAAV,OAAA;AACA,IAAAW,uBAAA,GAAAX,OAAA;AACA,IAAAY,QAAA,GAAAZ,OAAA;AAEA,MAAMa,MAAM,GAAGC,uBAAc,CAACC,KAAK,CAAC;EAAEC,GAAG,EAAE;AAA+B,CAAC,CAAC;AASrE,MAAMC,mBAAmB,GAAG,MAAOC,MAA2B,IAA4B;EAC/F,MAAM;IAAEC,OAAO;IAAEC,QAAQ;IAAEC,YAAY;IAAEC;EAAQ,CAAC,GAAGJ,MAAM;EAE3D,IAAIK,qBAAqB,CAACH,QAAQ,EAAEC,YAAY,CAAC,EAAE;IACjD,OAAOG,yBAAyB,CAACL,OAAO,EAAEC,QAAQ,EAAEC,YAAY,CAAC;EACnE;EAEA,IAAI,IAAAI,8CAAsB,EAACL,QAAQ,EAAEE,OAAO,CAAC,6CAA6C,CAAC,EAAE;IAC3F,OAAOI,oBAAY,CAACC,IAAI,CAAC,CAAC;EAC5B;EAEA,MAAMC,WAAW,GAAG,MAAMC,kBAAkB,CAACV,OAAO,CAAC;EACrD,IAAI,CAACS,WAAW,EAAE;IAChB,OAAO,IAAAE,gCAAe,EAACV,QAAQ,EAAEC,YAAY,CAAC;EAChD;EACA,IAAIO,WAAW,CAACN,OAAO,EAAE;IACvB,OAAOI,oBAAY,CAACC,IAAI,CAAC;MACvBL,OAAO,EAAEM,WAAW,CAACN,OAAO;MAC5BH,OAAO,EAAE;QACPG,OAAO,EAAEM,WAAW,CAACG;MACvB;IACF,CAAC,CAAC;EACJ;EACA,OAAOL,oBAAY,CAACC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAACK,OAAA,CAAAf,mBAAA,GAAAA,mBAAA;AAEF,MAAMgB,mCAAmC,GAAG;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEO,MAAMC,gBAAgB,GAAGA,CAC9BC,GAA8B,EAC9BC,cAAc,GAAG,KAAK,KACyB;EAC/C,MAAMvB,MAAM,GAAGC,uBAAc,CAACC,KAAK,CAAC;IAAEC,GAAG,EAAE;EAA+B,CAAC,CAAC;EAC5E,MAAMqB,OAAO,GAAGC,gBAAa,CAACC,2BAA2B,CAACJ,GAAG,CAAC;EAC9D,IAAI,CAACC,cAAc,EAAE;IACnBvB,MAAM,CAAC2B,IAAI,CAACP,mCAAmC,CAAC;EAClD;EACA,OAAO,IAAAQ,sBAAa,EAACJ,OAAO,EAAEK,uBAAc,CAAC;AAC/C,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AA9CAV,OAAA,CAAAE,gBAAA,GAAAA,gBAAA;AA+CO,MAAML,kBAAkB,GAAG,MAAOM,GAA8B,IAA+C;EACpH,MAAMQ,cAAc,GAAGL,gBAAa,CAACC,2BAA2B,CAACJ,GAAG,CAAC;EACrE,IAAIS,eAAe,GAAG,MAAM,IAAAH,sBAAa,EAACE,cAAc,EAAED,uBAAc,CAAC;EACzE,IAAIE,eAAe,EAAE;IACnB/B,MAAM,CAACgC,KAAK,CAAC,sCAAsC,CAAC;IACpD,OAAO;MACLC,OAAO,EAAEF;IACX,CAAC;EACH;EAEA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","ignoreList":[]}
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontegg/nextjs",
|
|
3
3
|
"libName": "FronteggNextJs",
|
|
4
|
-
"version": "9.2.14-alpha.
|
|
4
|
+
"version": "9.2.14-alpha.34330679131",
|
|
5
5
|
"author": "Frontegg LTD",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -23,7 +23,14 @@
|
|
|
23
23
|
"build:stable": "node ../../scripts/build node",
|
|
24
24
|
"build:types": "tsc -b tsconfig.build.json",
|
|
25
25
|
"build:copy-files": "node ../../scripts/copy-files.js",
|
|
26
|
-
"test": "node ../../scripts/prepare-env-test-file.js && CI=true npx playwright test",
|
|
26
|
+
"test": "yarn test:unit && node ../../scripts/prepare-env-test-file.js && CI=true PW_SKIP_WEBSERVER=1 npx playwright test --project=unit-playwright",
|
|
27
|
+
"test:unit": "vitest run",
|
|
28
|
+
"test:unit:watch": "vitest",
|
|
29
|
+
"test:unit:coverage": "vitest run --coverage",
|
|
30
|
+
"test:e2e": "playwright test",
|
|
31
|
+
"test:e2e:unit": "PW_SKIP_WEBSERVER=1 playwright test --project=unit-playwright",
|
|
32
|
+
"test:e2e:mocked": "playwright test --project=e2e-mocked",
|
|
33
|
+
"test:e2e:real": "playwright test --project=e2e-real",
|
|
27
34
|
"lint-json": "eslint -c .eslintrc.json -o ./lint-report.json --format json --no-color ./src/**/*.{ts,tsx}"
|
|
28
35
|
},
|
|
29
36
|
"dependencies": {
|
package/sdkVersion.js
CHANGED
package/sdkVersion.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdkVersion.js","names":["version"],"sources":["../../../packages/nextjs/src/sdkVersion.ts"],"sourcesContent":["export default { version: '9.2.14-alpha.
|
|
1
|
+
{"version":3,"file":"sdkVersion.js","names":["version"],"sources":["../../../packages/nextjs/src/sdkVersion.ts"],"sourcesContent":["export default { version: '9.2.14-alpha.34330679131' };\n"],"mappings":";;;;;;iCAAe;EAAEA,OAAO,EAAE;AAA2B,CAAC","ignoreList":[]}
|
|
@@ -11,7 +11,7 @@ export declare function refreshAccessTokenHostedLogin(request: IncomingMessage):
|
|
|
11
11
|
*/
|
|
12
12
|
export declare function isRuntimeNextRequest(url: string): boolean;
|
|
13
13
|
/**
|
|
14
|
-
* If url
|
|
14
|
+
* If url points at the hosted login callback route means that the user navigated back
|
|
15
15
|
* from frontegg hosted login, in this scenario no need to SSR refresh token
|
|
16
16
|
*/
|
|
17
17
|
export declare function isOauthCallback(url: string): boolean;
|
|
@@ -20,6 +20,7 @@ var _api = _interopRequireDefault(require("../../api"));
|
|
|
20
20
|
var _common = require("../../common");
|
|
21
21
|
var _config = _interopRequireDefault(require("../../config"));
|
|
22
22
|
var _constants = require("../common/constants");
|
|
23
|
+
var _routing = require("../routing");
|
|
23
24
|
function hasRefreshTokenCookie(cookies) {
|
|
24
25
|
if (cookies == null) {
|
|
25
26
|
return false;
|
|
@@ -94,11 +95,13 @@ function isRuntimeNextRequest(url) {
|
|
|
94
95
|
}
|
|
95
96
|
|
|
96
97
|
/**
|
|
97
|
-
* If url
|
|
98
|
+
* If url points at the hosted login callback route means that the user navigated back
|
|
98
99
|
* from frontegg hosted login, in this scenario no need to SSR refresh token
|
|
99
100
|
*/
|
|
100
101
|
function isOauthCallback(url) {
|
|
101
|
-
|
|
102
|
+
const [pathname, query] = url.split('?');
|
|
103
|
+
const hasCode = new URLSearchParams(query != null ? query : '').get('code') != null;
|
|
104
|
+
return (0, _routing.isHostedLoginCallbackPath)(pathname, hasCode);
|
|
102
105
|
}
|
|
103
106
|
|
|
104
107
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","names":["_fronteggLogger","_interopRequireDefault","require","_cookies","_api","_common","_config","_constants","hasRefreshTokenCookie","cookies","logger","fronteggLogger","child","tag","refreshTokenKey","CookieManager","debug","cookieKey","Object","keys","find","cookie","replace","exists","refreshAccessTokenEmbedded","request","headers","info","config","appId","api","refreshTokenEmbedded","refreshAccessTokenHostedLogin","sealFromCookies","getSessionCookieFromRequest","tokens","getTokensFromCookie","refreshToken","secureJwtEnabled","clientId","clientSecret","refreshTokenHostedLogin","e","error","isRuntimeNextRequest","url","startsWith","isOauthCallback","isSamlCallback","isSSOPostRequest","hasSetSessionCookie","cookieHeader","cookieName","indexOf","Array","isArray","some","header","saveForwardedSession","holder","session","FRONTEGG_FORWARDED_SESSION_KEY","getForwardedSession"],"sources":["../../../../../packages/nextjs/src/utils/refreshAccessTokenIfNeeded/helpers.ts"],"sourcesContent":["import fronteggLogger from '../fronteggLogger';\nimport CookieManager from '../cookies';\nimport { NextApiRequest } from 'next/dist/shared/lib/utils';\nimport api from '../../api';\nimport { getTokensFromCookie } from '../../common';\nimport { IncomingMessage } from 'http';\nimport config from '../../config';\n\nimport { FRONTEGG_FORWARDED_SESSION_KEY } from '../common/constants';\nimport { FronteggNextJSSession } from '../../types';\n\nexport function hasRefreshTokenCookie(cookies: Record<string, any>): boolean {\n if (cookies == null) {\n return false;\n }\n const logger = fronteggLogger.child({ tag: 'refreshToken.hasRefreshTokenCookie' });\n const refreshTokenKey = CookieManager.refreshTokenKey;\n logger.debug(`Checking if '${refreshTokenKey}' exists in cookies`);\n const cookieKey = Object.keys(cookies).find((cookie) => {\n return cookie.replace(/-/g, '') === refreshTokenKey;\n });\n const exists: boolean = cookieKey != null;\n logger.debug(`Cookie '${refreshTokenKey}' ${exists ? 'exists' : 'NOT exists'} in cookies`);\n return exists;\n}\n\nexport async function refreshAccessTokenEmbedded(request: IncomingMessage): Promise<Response | null> {\n const logger = fronteggLogger.child({ tag: 'refreshToken.refreshAccessTokenEmbedded' });\n\n const headers = request.headers as Record<string, string>;\n const cookies = (request as NextApiRequest).cookies;\n\n logger.info('check if has refresh token headers');\n if (hasRefreshTokenCookie(cookies)) {\n logger.info('going to refresh token (embedded mode)');\n if (config.appId) {\n headers['frontegg-requested-application-id'] = config.appId;\n }\n return await api.refreshTokenEmbedded(headers);\n }\n return null;\n}\n\nexport async function refreshAccessTokenHostedLogin(request: IncomingMessage): Promise<Response | null> {\n const logger = fronteggLogger.child({ tag: 'refreshToken.refreshAccessTokenHostedLogin' });\n const headers = request.headers as Record<string, string>;\n\n logger.info('trying to get token from cookies');\n\n const sealFromCookies = CookieManager.getSessionCookieFromRequest(request);\n try {\n const tokens = await getTokensFromCookie(sealFromCookies);\n if (!tokens?.refreshToken) {\n logger.info('refresh token not found');\n return null;\n }\n if (config.appId) {\n headers['frontegg-requested-application-id'] = config.appId;\n }\n if (config.secureJwtEnabled) {\n const clientId = config.clientId;\n const clientSecret = config.clientSecret;\n\n logger.info('going to refresh token (hosted-login mode) (secure-jwt mode)');\n return await api.refreshTokenHostedLogin(headers, tokens.refreshToken, clientId, clientSecret);\n } else {\n logger.info('going to refresh token (hosted-login mode) ', tokens.refreshToken);\n return await api.refreshTokenHostedLogin(headers, tokens.refreshToken);\n }\n } catch (e) {\n logger.error(e);\n return null;\n }\n}\n\n/**\n * If url starts with /_next/ means that the user trying to navigate\n * to a new nextjs page, in this scenario no need to refresh token\n * we can just return the actual stateless session from\n * the encrypted cookie\n */\nexport function isRuntimeNextRequest(url: string): boolean {\n return url.startsWith('/_next/');\n}\n\n/**\n * If url starts with '/oauth/callback' means that the user navigated back\n * from frontegg hosted login, in this scenario no need to SSR refresh token\n */\nexport function isOauthCallback(url: string): boolean {\n return url.startsWith('/oauth/callback');\n}\n\n/**\n * If url starts with '/account/saml/callback' means that the user navigated back\n * from sso login, in this scenario no need to SSR refresh token\n */\nexport function isSamlCallback(url: string): boolean {\n return url.startsWith('/account/saml/callback') || url.startsWith('/account/oidc/callback');\n}\n\n/**\n * If the url equals to '/frontegg/auth/{provider}/callback', it means that the SSO provider\n * is posting an http request to the nextjs backend middleware after successfully logged in the user\n */\nexport function isSSOPostRequest(url: string): boolean {\n return url === '/frontegg/auth/saml/callback' || url === '/frontegg/auth/oidc/callback';\n}\n\n/**\n * This function verifies if the headers includes a 'set-cookie' header\n * from a prior refresh token request. If it's the case, we can infer that the\n * session cookie has been initialized, thus we can disable the double refresh token\n * for server-side redirects such as '/_error' or any other server-side redirects.\n */\nexport function hasSetSessionCookie(cookieHeader: number | string | string[] | undefined): boolean {\n if (!cookieHeader || typeof cookieHeader === 'number') {\n return false;\n }\n const cookieName = config.cookieName;\n if (typeof cookieHeader === 'string') {\n return cookieHeader.indexOf(cookieName) !== -1;\n }\n if (Array.isArray(cookieHeader)) {\n return cookieHeader.some((header) => header.startsWith(cookieName));\n }\n return false;\n}\n\n/**\n * This function stores the Frontegg session instance for use\n * within the Next.js application during the token refresh process\n * in the redirect request page.\n */\nexport function saveForwardedSession(holder: any, session: FronteggNextJSSession | undefined) {\n holder[FRONTEGG_FORWARDED_SESSION_KEY] = session;\n}\n\n/**\n * This function retrieves the stored session from the previous redirected page request.\n * This helps in preventing the token from being refreshed twice during a single client page request.\n */\n\nexport function getForwardedSession(holder: any): FronteggNextJSSession | null {\n return holder[FRONTEGG_FORWARDED_SESSION_KEY];\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"helpers.js","names":["_fronteggLogger","_interopRequireDefault","require","_cookies","_api","_common","_config","_constants","_routing","hasRefreshTokenCookie","cookies","logger","fronteggLogger","child","tag","refreshTokenKey","CookieManager","debug","cookieKey","Object","keys","find","cookie","replace","exists","refreshAccessTokenEmbedded","request","headers","info","config","appId","api","refreshTokenEmbedded","refreshAccessTokenHostedLogin","sealFromCookies","getSessionCookieFromRequest","tokens","getTokensFromCookie","refreshToken","secureJwtEnabled","clientId","clientSecret","refreshTokenHostedLogin","e","error","isRuntimeNextRequest","url","startsWith","isOauthCallback","pathname","query","split","hasCode","URLSearchParams","get","isHostedLoginCallbackPath","isSamlCallback","isSSOPostRequest","hasSetSessionCookie","cookieHeader","cookieName","indexOf","Array","isArray","some","header","saveForwardedSession","holder","session","FRONTEGG_FORWARDED_SESSION_KEY","getForwardedSession"],"sources":["../../../../../packages/nextjs/src/utils/refreshAccessTokenIfNeeded/helpers.ts"],"sourcesContent":["import fronteggLogger from '../fronteggLogger';\nimport CookieManager from '../cookies';\nimport { NextApiRequest } from 'next/dist/shared/lib/utils';\nimport api from '../../api';\nimport { getTokensFromCookie } from '../../common';\nimport { IncomingMessage } from 'http';\nimport config from '../../config';\n\nimport { FRONTEGG_FORWARDED_SESSION_KEY } from '../common/constants';\nimport { isHostedLoginCallbackPath } from '../routing';\nimport { FronteggNextJSSession } from '../../types';\n\nexport function hasRefreshTokenCookie(cookies: Record<string, any>): boolean {\n if (cookies == null) {\n return false;\n }\n const logger = fronteggLogger.child({ tag: 'refreshToken.hasRefreshTokenCookie' });\n const refreshTokenKey = CookieManager.refreshTokenKey;\n logger.debug(`Checking if '${refreshTokenKey}' exists in cookies`);\n const cookieKey = Object.keys(cookies).find((cookie) => {\n return cookie.replace(/-/g, '') === refreshTokenKey;\n });\n const exists: boolean = cookieKey != null;\n logger.debug(`Cookie '${refreshTokenKey}' ${exists ? 'exists' : 'NOT exists'} in cookies`);\n return exists;\n}\n\nexport async function refreshAccessTokenEmbedded(request: IncomingMessage): Promise<Response | null> {\n const logger = fronteggLogger.child({ tag: 'refreshToken.refreshAccessTokenEmbedded' });\n\n const headers = request.headers as Record<string, string>;\n const cookies = (request as NextApiRequest).cookies;\n\n logger.info('check if has refresh token headers');\n if (hasRefreshTokenCookie(cookies)) {\n logger.info('going to refresh token (embedded mode)');\n if (config.appId) {\n headers['frontegg-requested-application-id'] = config.appId;\n }\n return await api.refreshTokenEmbedded(headers);\n }\n return null;\n}\n\nexport async function refreshAccessTokenHostedLogin(request: IncomingMessage): Promise<Response | null> {\n const logger = fronteggLogger.child({ tag: 'refreshToken.refreshAccessTokenHostedLogin' });\n const headers = request.headers as Record<string, string>;\n\n logger.info('trying to get token from cookies');\n\n const sealFromCookies = CookieManager.getSessionCookieFromRequest(request);\n try {\n const tokens = await getTokensFromCookie(sealFromCookies);\n if (!tokens?.refreshToken) {\n logger.info('refresh token not found');\n return null;\n }\n if (config.appId) {\n headers['frontegg-requested-application-id'] = config.appId;\n }\n if (config.secureJwtEnabled) {\n const clientId = config.clientId;\n const clientSecret = config.clientSecret;\n\n logger.info('going to refresh token (hosted-login mode) (secure-jwt mode)');\n return await api.refreshTokenHostedLogin(headers, tokens.refreshToken, clientId, clientSecret);\n } else {\n logger.info('going to refresh token (hosted-login mode) ', tokens.refreshToken);\n return await api.refreshTokenHostedLogin(headers, tokens.refreshToken);\n }\n } catch (e) {\n logger.error(e);\n return null;\n }\n}\n\n/**\n * If url starts with /_next/ means that the user trying to navigate\n * to a new nextjs page, in this scenario no need to refresh token\n * we can just return the actual stateless session from\n * the encrypted cookie\n */\nexport function isRuntimeNextRequest(url: string): boolean {\n return url.startsWith('/_next/');\n}\n\n/**\n * If url points at the hosted login callback route means that the user navigated back\n * from frontegg hosted login, in this scenario no need to SSR refresh token\n */\nexport function isOauthCallback(url: string): boolean {\n const [pathname, query] = url.split('?');\n const hasCode = new URLSearchParams(query ?? '').get('code') != null;\n return isHostedLoginCallbackPath(pathname, hasCode);\n}\n\n/**\n * If url starts with '/account/saml/callback' means that the user navigated back\n * from sso login, in this scenario no need to SSR refresh token\n */\nexport function isSamlCallback(url: string): boolean {\n return url.startsWith('/account/saml/callback') || url.startsWith('/account/oidc/callback');\n}\n\n/**\n * If the url equals to '/frontegg/auth/{provider}/callback', it means that the SSO provider\n * is posting an http request to the nextjs backend middleware after successfully logged in the user\n */\nexport function isSSOPostRequest(url: string): boolean {\n return url === '/frontegg/auth/saml/callback' || url === '/frontegg/auth/oidc/callback';\n}\n\n/**\n * This function verifies if the headers includes a 'set-cookie' header\n * from a prior refresh token request. If it's the case, we can infer that the\n * session cookie has been initialized, thus we can disable the double refresh token\n * for server-side redirects such as '/_error' or any other server-side redirects.\n */\nexport function hasSetSessionCookie(cookieHeader: number | string | string[] | undefined): boolean {\n if (!cookieHeader || typeof cookieHeader === 'number') {\n return false;\n }\n const cookieName = config.cookieName;\n if (typeof cookieHeader === 'string') {\n return cookieHeader.indexOf(cookieName) !== -1;\n }\n if (Array.isArray(cookieHeader)) {\n return cookieHeader.some((header) => header.startsWith(cookieName));\n }\n return false;\n}\n\n/**\n * This function stores the Frontegg session instance for use\n * within the Next.js application during the token refresh process\n * in the redirect request page.\n */\nexport function saveForwardedSession(holder: any, session: FronteggNextJSSession | undefined) {\n holder[FRONTEGG_FORWARDED_SESSION_KEY] = session;\n}\n\n/**\n * This function retrieves the stored session from the previous redirected page request.\n * This helps in preventing the token from being refreshed twice during a single client page request.\n */\n\nexport function getForwardedSession(holder: any): FronteggNextJSSession | null {\n return holder[FRONTEGG_FORWARDED_SESSION_KEY];\n}\n"],"mappings":"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","ignoreList":[]}
|
package/utils/routing/index.d.ts
CHANGED
|
@@ -22,3 +22,27 @@ export declare function getAuthRoutes(): {
|
|
|
22
22
|
routesObj: Record<string, string>;
|
|
23
23
|
};
|
|
24
24
|
export declare function isAuthRoute(pathname: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Resolve the hosted login callback path, honoring an application level override of
|
|
27
|
+
* `authOptions.routes.hostedLoginRedirectUrl`.
|
|
28
|
+
*
|
|
29
|
+
* The middleware callback detection and the authorization code exchange must agree on
|
|
30
|
+
* this value: the `redirect_uri` sent at exchange time has to match the one the code was
|
|
31
|
+
* issued against, otherwise the exchange is rejected.
|
|
32
|
+
*/
|
|
33
|
+
export declare function getHostedLoginRedirectPath(): string;
|
|
34
|
+
/**
|
|
35
|
+
* Build the absolute `redirect_uri` used for the hosted login authorization code exchange.
|
|
36
|
+
*
|
|
37
|
+
* When the callback path is the application root the path is dropped entirely, so the
|
|
38
|
+
* resulting URI is the bare app URL rather than a trailing slash variant of it.
|
|
39
|
+
*/
|
|
40
|
+
export declare function buildHostedLoginRedirectUri(): string;
|
|
41
|
+
/**
|
|
42
|
+
* Whether a request path is the hosted login callback.
|
|
43
|
+
*
|
|
44
|
+
* An application may point the callback at its root, in which case the path alone matches
|
|
45
|
+
* everything and the authorization code is what tells a callback apart from a normal page
|
|
46
|
+
* request.
|
|
47
|
+
*/
|
|
48
|
+
export declare function isHostedLoginCallbackPath(pathname: string, hasCode: boolean): boolean;
|
package/utils/routing/index.js
CHANGED
|
@@ -4,9 +4,12 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
+
exports.buildHostedLoginRedirectUri = buildHostedLoginRedirectUri;
|
|
7
8
|
exports.defaultFronteggRoutes = void 0;
|
|
8
9
|
exports.getAuthRoutes = getAuthRoutes;
|
|
10
|
+
exports.getHostedLoginRedirectPath = getHostedLoginRedirectPath;
|
|
9
11
|
exports.isAuthRoute = isAuthRoute;
|
|
12
|
+
exports.isHostedLoginCallbackPath = isHostedLoginCallbackPath;
|
|
10
13
|
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
11
14
|
var _config = _interopRequireDefault(require("../../config"));
|
|
12
15
|
const defaultFronteggRoutes = exports.defaultFronteggRoutes = {
|
|
@@ -47,4 +50,57 @@ function isAuthRoute(pathname) {
|
|
|
47
50
|
return pathname !== routesObj.authenticatedUrl && routesArr.indexOf(pathname) !== -1;
|
|
48
51
|
}
|
|
49
52
|
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Resolve the hosted login callback path, honoring an application level override of
|
|
56
|
+
* `authOptions.routes.hostedLoginRedirectUrl`.
|
|
57
|
+
*
|
|
58
|
+
* The middleware callback detection and the authorization code exchange must agree on
|
|
59
|
+
* this value: the `redirect_uri` sent at exchange time has to match the one the code was
|
|
60
|
+
* issued against, otherwise the exchange is rejected.
|
|
61
|
+
*/
|
|
62
|
+
function getHostedLoginRedirectPath() {
|
|
63
|
+
var _config$authRoutes$ho, _config$authRoutes;
|
|
64
|
+
const path = (_config$authRoutes$ho = (_config$authRoutes = _config.default.authRoutes) == null ? void 0 : _config$authRoutes.hostedLoginRedirectUrl) != null ? _config$authRoutes$ho : defaultFronteggRoutes.hostedLoginRedirectUrl;
|
|
65
|
+
return path.startsWith('/') ? path : `/${path}`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Build the absolute `redirect_uri` used for the hosted login authorization code exchange.
|
|
70
|
+
*
|
|
71
|
+
* When the callback path is the application root the path is dropped entirely, so the
|
|
72
|
+
* resulting URI is the bare app URL rather than a trailing slash variant of it.
|
|
73
|
+
*/
|
|
74
|
+
function buildHostedLoginRedirectUri() {
|
|
75
|
+
const path = getHostedLoginRedirectPath();
|
|
76
|
+
if (path === '/') {
|
|
77
|
+
/**
|
|
78
|
+
* The callback is the app root, so the URI is the app URL with no path appended.
|
|
79
|
+
* A trailing slash is dropped here because the redirect being matched carries no
|
|
80
|
+
* path at all.
|
|
81
|
+
*/
|
|
82
|
+
return _config.default.appUrl.endsWith('/') ? _config.default.appUrl.slice(0, -1) : _config.default.appUrl;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Concatenated verbatim, without normalizing a trailing slash on the app URL. This
|
|
86
|
+
* value has to match the `redirect_uri` sent at authorize time, which is built from
|
|
87
|
+
* the same unnormalized app URL, so normalizing only one side would break the exchange.
|
|
88
|
+
*/
|
|
89
|
+
return `${_config.default.appUrl}${path}`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Whether a request path is the hosted login callback.
|
|
94
|
+
*
|
|
95
|
+
* An application may point the callback at its root, in which case the path alone matches
|
|
96
|
+
* everything and the authorization code is what tells a callback apart from a normal page
|
|
97
|
+
* request.
|
|
98
|
+
*/
|
|
99
|
+
function isHostedLoginCallbackPath(pathname, hasCode) {
|
|
100
|
+
const path = getHostedLoginRedirectPath();
|
|
101
|
+
if (path === '/') {
|
|
102
|
+
return hasCode;
|
|
103
|
+
}
|
|
104
|
+
return pathname.startsWith(path);
|
|
105
|
+
}
|
|
50
106
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_config","_interopRequireDefault","require","defaultFronteggRoutes","exports","authenticatedUrl","loginUrl","stepUpUrl","logoutUrl","activateUrl","impersonationUrl","acceptInvitationUrl","forgetPasswordUrl","resetPhoneNumberUrl","resetPasswordUrl","socialLoginCallbackUrl","signUpUrl","oidcRedirectUrl","samlCallbackUrl","magicLinkCallbackUrl","hostedLoginRedirectUrl","openAppUrl","getAuthRoutes","routesObj","_extends2","default","config","authRoutes","routesArr","Object","keys","reduce","p","key","isAuthRoute","pathname","isHostedLogin","indexOf"],"sources":["../../../../../packages/nextjs/src/utils/routing/index.ts"],"sourcesContent":["import config from '../../config';\n\nexport const defaultFronteggRoutes = {\n authenticatedUrl: '/',\n loginUrl: '/account/login',\n stepUpUrl: '/account/step-up',\n logoutUrl: '/account/logout',\n activateUrl: '/account/activate',\n impersonationUrl: '/account/impersonate',\n acceptInvitationUrl: '/account/invitation/accept',\n forgetPasswordUrl: '/account/forget-password',\n resetPhoneNumberUrl: '/account/reset-phone-number',\n resetPasswordUrl: '/account/reset-password',\n socialLoginCallbackUrl: '/account/social/success',\n signUpUrl: '/account/sign-up',\n oidcRedirectUrl: '/account/oidc/callback',\n samlCallbackUrl: '/account/saml/callback',\n magicLinkCallbackUrl: '/account/login/magic-link',\n hostedLoginRedirectUrl: '/oauth/callback',\n openAppUrl: '/account/redirect',\n};\n\nexport function getAuthRoutes(): { routesArr: string[]; routesObj: Record<string, string> } {\n const routesObj = {\n ...defaultFronteggRoutes,\n ...config.authRoutes,\n };\n const routesArr: string[] = Object.keys(routesObj).reduce(\n (p: string[], key: string) => [...p, (routesObj as any)[key]],\n []\n );\n return { routesArr, routesObj };\n}\n\nexport function isAuthRoute(pathname: string): boolean {\n const { routesArr, routesObj } = getAuthRoutes();\n\n if (config.isHostedLogin) {\n return (\n routesObj.loginUrl === pathname ||\n routesObj.logoutUrl === pathname ||\n routesObj.hostedLoginRedirectUrl === pathname\n );\n } else {\n return pathname !== routesObj.authenticatedUrl && routesArr.indexOf(pathname) !== -1;\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":["_config","_interopRequireDefault","require","defaultFronteggRoutes","exports","authenticatedUrl","loginUrl","stepUpUrl","logoutUrl","activateUrl","impersonationUrl","acceptInvitationUrl","forgetPasswordUrl","resetPhoneNumberUrl","resetPasswordUrl","socialLoginCallbackUrl","signUpUrl","oidcRedirectUrl","samlCallbackUrl","magicLinkCallbackUrl","hostedLoginRedirectUrl","openAppUrl","getAuthRoutes","routesObj","_extends2","default","config","authRoutes","routesArr","Object","keys","reduce","p","key","isAuthRoute","pathname","isHostedLogin","indexOf","getHostedLoginRedirectPath","_config$authRoutes$ho","_config$authRoutes","path","startsWith","buildHostedLoginRedirectUri","appUrl","endsWith","slice","isHostedLoginCallbackPath","hasCode"],"sources":["../../../../../packages/nextjs/src/utils/routing/index.ts"],"sourcesContent":["import config from '../../config';\n\nexport const defaultFronteggRoutes = {\n authenticatedUrl: '/',\n loginUrl: '/account/login',\n stepUpUrl: '/account/step-up',\n logoutUrl: '/account/logout',\n activateUrl: '/account/activate',\n impersonationUrl: '/account/impersonate',\n acceptInvitationUrl: '/account/invitation/accept',\n forgetPasswordUrl: '/account/forget-password',\n resetPhoneNumberUrl: '/account/reset-phone-number',\n resetPasswordUrl: '/account/reset-password',\n socialLoginCallbackUrl: '/account/social/success',\n signUpUrl: '/account/sign-up',\n oidcRedirectUrl: '/account/oidc/callback',\n samlCallbackUrl: '/account/saml/callback',\n magicLinkCallbackUrl: '/account/login/magic-link',\n hostedLoginRedirectUrl: '/oauth/callback',\n openAppUrl: '/account/redirect',\n};\n\nexport function getAuthRoutes(): { routesArr: string[]; routesObj: Record<string, string> } {\n const routesObj = {\n ...defaultFronteggRoutes,\n ...config.authRoutes,\n };\n const routesArr: string[] = Object.keys(routesObj).reduce(\n (p: string[], key: string) => [...p, (routesObj as any)[key]],\n []\n );\n return { routesArr, routesObj };\n}\n\nexport function isAuthRoute(pathname: string): boolean {\n const { routesArr, routesObj } = getAuthRoutes();\n\n if (config.isHostedLogin) {\n return (\n routesObj.loginUrl === pathname ||\n routesObj.logoutUrl === pathname ||\n routesObj.hostedLoginRedirectUrl === pathname\n );\n } else {\n return pathname !== routesObj.authenticatedUrl && routesArr.indexOf(pathname) !== -1;\n }\n}\n\n/**\n * Resolve the hosted login callback path, honoring an application level override of\n * `authOptions.routes.hostedLoginRedirectUrl`.\n *\n * The middleware callback detection and the authorization code exchange must agree on\n * this value: the `redirect_uri` sent at exchange time has to match the one the code was\n * issued against, otherwise the exchange is rejected.\n */\nexport function getHostedLoginRedirectPath(): string {\n const path = config.authRoutes?.hostedLoginRedirectUrl ?? defaultFronteggRoutes.hostedLoginRedirectUrl;\n return path.startsWith('/') ? path : `/${path}`;\n}\n\n/**\n * Build the absolute `redirect_uri` used for the hosted login authorization code exchange.\n *\n * When the callback path is the application root the path is dropped entirely, so the\n * resulting URI is the bare app URL rather than a trailing slash variant of it.\n */\nexport function buildHostedLoginRedirectUri(): string {\n const path = getHostedLoginRedirectPath();\n if (path === '/') {\n /**\n * The callback is the app root, so the URI is the app URL with no path appended.\n * A trailing slash is dropped here because the redirect being matched carries no\n * path at all.\n */\n return config.appUrl.endsWith('/') ? config.appUrl.slice(0, -1) : config.appUrl;\n }\n /**\n * Concatenated verbatim, without normalizing a trailing slash on the app URL. This\n * value has to match the `redirect_uri` sent at authorize time, which is built from\n * the same unnormalized app URL, so normalizing only one side would break the exchange.\n */\n return `${config.appUrl}${path}`;\n}\n\n/**\n * Whether a request path is the hosted login callback.\n *\n * An application may point the callback at its root, in which case the path alone matches\n * everything and the authorization code is what tells a callback apart from a normal page\n * request.\n */\nexport function isHostedLoginCallbackPath(pathname: string, hasCode: boolean): boolean {\n const path = getHostedLoginRedirectPath();\n if (path === '/') {\n return hasCode;\n }\n return pathname.startsWith(path);\n}\n"],"mappings":"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","ignoreList":[]}
|