From 6be8a71e30e49609d1fb44e5ec202ae39044b8e3 Mon Sep 17 00:00:00 2001 From: Serhii Zautkin Date: Fri, 24 Apr 2026 11:18:20 -0700 Subject: [PATCH] CADC-15535 Auth routing fixes --- rafts/frontend/next.config.ts | 7 ++-- rafts/frontend/src/app/api/auth/sso/route.ts | 11 +++---- rafts/frontend/src/proxy.ts | 34 +++++++++++++------- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/rafts/frontend/next.config.ts b/rafts/frontend/next.config.ts index 8d51b51..52bfb29 100644 --- a/rafts/frontend/next.config.ts +++ b/rafts/frontend/next.config.ts @@ -35,10 +35,9 @@ const securityHeaders = [ ] const nextConfig: NextConfig = { - // Add these for CANFAR compatibility - // Use the BASE_PATH from environment if available - basePath: process.env.NEXT_PUBLIC_BASE_PATH || '', - assetPrefix: process.env.NEXT_PUBLIC_BASE_PATH || '', + // CANFAR deployment: app always runs at /rafts + basePath: '/rafts', + assetPrefix: '/rafts', // Trust the proxy headers poweredByHeader: false, diff --git a/rafts/frontend/src/app/api/auth/sso/route.ts b/rafts/frontend/src/app/api/auth/sso/route.ts index 2cc87b3..868961c 100644 --- a/rafts/frontend/src/app/api/auth/sso/route.ts +++ b/rafts/frontend/src/app/api/auth/sso/route.ts @@ -65,23 +65,22 @@ ************************************************************************ */ -import { NextRequest, NextResponse } from 'next/server' +import { NextRequest } from 'next/server' +import { redirect } from 'next/navigation' import { signIn } from '@/auth/cadc-auth/credentials' import { parseCADCSSOCookie } from '@/auth/cadc-auth/parseCADCSSOCookie' -const basePath = process.env.NEXT_PUBLIC_BASE_PATH || '' - export async function GET(request: NextRequest) { const cadcSso = request.cookies.get('CADC_SSO')?.value const returnUrl = request.nextUrl.searchParams.get('returnUrl') || '/' if (!cadcSso) { - return NextResponse.redirect(new URL(`${basePath}/login`, request.url)) + redirect('/login') } const tokenInfo = parseCADCSSOCookie(cadcSso) if (!tokenInfo) { - return NextResponse.redirect(new URL(`${basePath}/login`, request.url)) + redirect('/login') } try { @@ -99,6 +98,6 @@ export async function GET(request: NextRequest) { } // For other errors (e.g. CADC APIs rejected the token), fall through to login console.error('[SSO] Auto-login failed:', error) - return NextResponse.redirect(new URL(`${basePath}/login`, request.url)) + redirect('/login') } } diff --git a/rafts/frontend/src/proxy.ts b/rafts/frontend/src/proxy.ts index f21ffe5..383a7a7 100644 --- a/rafts/frontend/src/proxy.ts +++ b/rafts/frontend/src/proxy.ts @@ -126,6 +126,27 @@ const proxy = async (request: NextRequest) => { return response } + // SSO auto-login: if no session but CADC_SSO cookie is present, bootstrap a session. + // This runs on ALL pages (public and protected) so the user appears logged in everywhere. + // Skip paths that would cause loops (login, SSO endpoint itself). + const isStaleSession = session && (!session.user?.name || session.user.name.includes('undefined')) + const ssoSkipPaths = ['/login', '/login-required', '/api/auth'] + const shouldSkipSso = ssoSkipPaths.some((p) => pathnameWithoutLocale.startsWith(p)) + + if ((!session || isStaleSession) && !shouldSkipSso) { + const cadcSso = request.cookies.get('CADC_SSO')?.value + const ssoToken = cadcSso ? parseCADCSSOCookie(cadcSso) : null + + if (cadcSso && ssoToken) { + const returnPath = request.nextUrl.pathname || '/' + const ssoUrl = request.nextUrl.clone() + ssoUrl.pathname = '/api/auth/sso' + ssoUrl.searchParams.set('returnUrl', returnPath) + console.log('[Proxy] SSO redirect for', ssoToken.userID, 'from', returnPath) + return NextResponse.redirect(ssoUrl) + } + } + // Handle locale for non-API routes const response = await intlMiddleware(request) @@ -138,20 +159,9 @@ const proxy = async (request: NextRequest) => { return response } - // If not authenticated or session is stale (missing user name), try SSO or redirect to login - const isStaleSession = session && (!session.user?.name || session.user.name.includes('undefined')) + // Protected path without session — redirect to login if (!session || isStaleSession) { const returnPath = request.nextUrl.pathname || '/' - - // Check for CADC_SSO cookie — auto-login if the user is already authenticated with CANFAR - const cadcSso = request.cookies.get('CADC_SSO')?.value - if (cadcSso && parseCADCSSOCookie(cadcSso)) { - const ssoUrl = request.nextUrl.clone() - ssoUrl.pathname = '/api/auth/sso' - ssoUrl.searchParams.set('returnUrl', returnPath) - return NextResponse.redirect(ssoUrl) - } - const loginRequiredUrl = request.nextUrl.clone() loginRequiredUrl.pathname = '/login-required' loginRequiredUrl.searchParams.set('returnUrl', returnPath)