diff --git a/.changeset/no-redirect.md b/.changeset/no-redirect.md index 39df84dcf78..d37e15a7731 100644 --- a/.changeset/no-redirect.md +++ b/.changeset/no-redirect.md @@ -1,5 +1,5 @@ --- -'@keystone-6/core': patch +'@keystone-6/auth': patch --- Removes `?from` redirect from `/signin` page to prevent open redirection. diff --git a/.changeset/twelve-toes-punch.md b/.changeset/twelve-toes-punch.md new file mode 100644 index 00000000000..a64c640c415 --- /dev/null +++ b/.changeset/twelve-toes-punch.md @@ -0,0 +1,6 @@ +--- +'@keystone-6/core': patch +'@keystone-6/auth': patch +--- + +Adds `basePath` with a default of `'/'` to `pageMiddleware` to support redirects when using `ui.basePath` diff --git a/packages/auth/src/index.ts b/packages/auth/src/index.ts index a74a0c79910..31d66c8d8b0 100644 --- a/packages/auth/src/index.ts +++ b/packages/auth/src/index.ts @@ -117,13 +117,6 @@ export function createAuth({ return filesToWrite; }; - /** - * publicAuthPages - * - * Must be added to the ui.publicPages config - */ - const authPublicPages = ['/signin']; - /** * extendGraphqlSchema * @@ -214,28 +207,30 @@ export function createAuth({ async function authMiddleware({ context, wasAccessAllowed, + basePath, }: { context: KeystoneContext; wasAccessAllowed: boolean; + basePath: string; }): Promise<{ kind: 'redirect'; to: string } | void> { const { req } = context; const { pathname } = new URL(req!.url!, 'http://_'); // redirect to init if initFirstItem conditions are met - if (pathname !== '/init' && (await hasInitFirstItemConditions(context))) { - return { kind: 'redirect', to: '/init' }; + if (pathname !== `${basePath}/init` && (await hasInitFirstItemConditions(context))) { + return { kind: 'redirect', to: `${basePath}/init` }; } // redirect to / if attempting to /init and initFirstItem conditions are not met - if (pathname === '/init' && !(await hasInitFirstItemConditions(context))) { - return { kind: 'redirect', to: '/' }; + if (pathname === `${basePath}/init` && !(await hasInitFirstItemConditions(context))) { + return { kind: 'redirect', to: basePath }; } // don't redirect if we have access if (wasAccessAllowed) return; // otherwise, redirect to signin - return { kind: 'redirect', to: '/signin' }; + return { kind: 'redirect', to: `${basePath}/signin` }; } function defaultIsAccessAllowed({ session, sessionStrategy }: KeystoneContext) { @@ -263,6 +258,7 @@ export function createAuth({ pageMiddleware, publicPages = [], } = ui || {}; + const authPublicPages = [`${ui?.basePath ?? ''}/signin`]; ui = { ...ui, publicPages: [...publicPages, ...authPublicPages], diff --git a/packages/core/src/lib/server/createAdminUIMiddleware.ts b/packages/core/src/lib/server/createAdminUIMiddleware.ts index 451c918eef3..ef7c0347522 100644 --- a/packages/core/src/lib/server/createAdminUIMiddleware.ts +++ b/packages/core/src/lib/server/createAdminUIMiddleware.ts @@ -20,13 +20,20 @@ export function createAdminUIMiddlewareWithNextApp( const handle = nextApp.getRequestHandler(); const { - ui: { isAccessAllowed = defaultIsAccessAllowed, pageMiddleware, publicPages = [] } = {}, + ui: { + isAccessAllowed = defaultIsAccessAllowed, + pageMiddleware, + publicPages = [], + basePath = '', + } = {}, } = config; + if (basePath.endsWith('/')) throw new TypeError('basePath must not end with a trailing slash'); + return async (req: express.Request, res: express.Response) => { const { pathname } = url.parse(req.url); - if (pathname?.startsWith('/_next') || pathname?.startsWith('/__next')) { + if (pathname?.startsWith(`${basePath}/_next`) || pathname?.startsWith(`${basePath}/__next`)) { return handle(req, res); } @@ -38,6 +45,7 @@ export function createAdminUIMiddlewareWithNextApp( const shouldRedirect = await pageMiddleware?.({ context, wasAccessAllowed, + basePath, }); if (shouldRedirect) { diff --git a/packages/core/src/types/config/index.ts b/packages/core/src/types/config/index.ts index 7b022369282..570b8e95b50 100644 --- a/packages/core/src/types/config/index.ts +++ b/packages/core/src/types/config/index.ts @@ -181,6 +181,7 @@ export type AdminUIConfig = { pageMiddleware?: (args: { context: KeystoneContext; wasAccessAllowed: boolean; + basePath: string; }) => MaybePromise<{ kind: 'redirect'; to: string } | void>; };