diff --git a/src/app/auth/resource/[resourceGuid]/page.tsx b/src/app/auth/resource/[resourceGuid]/page.tsx index 4d6f101de..7f2ad6a27 100644 --- a/src/app/auth/resource/[resourceGuid]/page.tsx +++ b/src/app/auth/resource/[resourceGuid]/page.tsx @@ -122,11 +122,20 @@ export default async function ResourceAuthPage(props: { if (searchParams.redirect) { try { + const redirectTarget = new URL(searchParams.redirect); const serverResourceHost = new URL(authInfo.url).host; - const redirectHost = new URL(searchParams.redirect).host; - const redirectPort = new URL(searchParams.redirect).port; + const redirectHost = redirectTarget.host; + const redirectPort = redirectTarget.port; const serverResourceHostWithPort = `${serverResourceHost}:${redirectPort}`; + // URL parses a host out of any scheme that uses "//", so a target + // like javascript://resource-host/... matches the comparisons + // below. The target is later assigned to window.location, so only + // http(s) is accepted here. + const isHttpTarget = + redirectTarget.protocol === "http:" || + redirectTarget.protocol === "https:"; + const wildcardMatchesRedirect = ( wildcardDomain: string, host: string @@ -136,14 +145,16 @@ export default async function ResourceAuthPage(props: { return host.endsWith(suffix) && host.length > suffix.length; }; - if (serverResourceHost === redirectHost) { - redirectUrl = searchParams.redirect; - } else if (serverResourceHostWithPort === redirectHost) { - redirectUrl = searchParams.redirect; - } else if ( - authInfo.wildcard && - authInfo.fullDomain && - wildcardMatchesRedirect(authInfo.fullDomain, redirectHost) + if ( + isHttpTarget && + (serverResourceHost === redirectHost || + serverResourceHostWithPort === redirectHost || + (authInfo.wildcard && + authInfo.fullDomain && + wildcardMatchesRedirect( + authInfo.fullDomain, + redirectHost + ))) ) { redirectUrl = searchParams.redirect; }