diff --git a/app/api/auth/session/route.ts b/app/api/auth/session/route.ts index a21f526f..5711df57 100644 --- a/app/api/auth/session/route.ts +++ b/app/api/auth/session/route.ts @@ -4,7 +4,12 @@ import { logger } from '@/lib/logger'; import { encryptSession, decryptSession } from '@/lib/auth/crypto'; import { SESSION_COOKIE_MAX_AGE, sessionCookieName } from '@/lib/auth/session-cookie'; import { getCookieOptions } from '@/lib/oauth/cookie-config'; -import { JmapAuthVerificationError, verifyJmapAuth } from '@/lib/auth/verify-jmap-auth'; +import { + JmapAuthVerificationError, + normalizeJmapServerUrl, + validateProxyAuthHeader, + verifyJmapAuth, +} from '@/lib/auth/verify-jmap-auth'; import { clearStalwartAuthContextInStore, setStalwartAuthContextInStore, @@ -74,7 +79,13 @@ export async function POST(request: NextRequest) { const slot = typeof bodySlot === 'number' && bodySlot >= 0 && bodySlot < MAX_ACCOUNT_SLOTS ? bodySlot : getSlot(request); const cookieName = sessionCookieName(slot); const authHeader = `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}`; - const normalizedServerUrl = await verifyJmapAuth(upstreamUrl, authHeader, { trusted: upstreamTrusted }); + // Trusted (admin-configured) URLs skip the upstream re-fetch: the cookie + // we write here is only ever consumed for requests on behalf of this same + // user, so bogus credentials would just yield 401s downstream rather than + // privilege escalation. Untrusted custom endpoints still verify upstream. + const normalizedServerUrl = upstreamTrusted + ? (validateProxyAuthHeader(authHeader), normalizeJmapServerUrl(upstreamUrl)) + : await verifyJmapAuth(upstreamUrl, authHeader, { trusted: false }); const token = encryptSession(normalizedServerUrl, username, password); const cookieStore = await cookies(); cookieStore.set(cookieName, token, COOKIE_OPTIONS);