diff --git a/packages/core-app-api/src/lib/AuthConnector/DefaultAuthConnector.ts b/packages/core-app-api/src/lib/AuthConnector/DefaultAuthConnector.ts index 32d86b9757..d93e838f74 100644 --- a/packages/core-app-api/src/lib/AuthConnector/DefaultAuthConnector.ts +++ b/packages/core-app-api/src/lib/AuthConnector/DefaultAuthConnector.ts @@ -202,13 +202,17 @@ export class DefaultAuthConnector if (contentType?.includes('application/json')) { const body = await res.json(); if (body.logoutUrl) { - window.location.href = body.logoutUrl; - return new Promise(() => {}); + const url = new URL(body.logoutUrl); + if (url.protocol === 'https:' || url.hostname === 'localhost') { + window.location.href = body.logoutUrl; + return new Promise(() => {}); + } } } } catch { - // Provider logout redirect is best-effort — the Backstage session is - // already cleared, so we degrade gracefully. + // Provider logout redirect is best-effort - the backend session + // (refresh token cookie and persisted scopes) is already cleared, + // so we degrade gracefully. } return undefined; diff --git a/plugins/auth-node/src/oauth/createOAuthRouteHandlers.ts b/plugins/auth-node/src/oauth/createOAuthRouteHandlers.ts index d12060b20f..e5967bb1d6 100644 --- a/plugins/auth-node/src/oauth/createOAuthRouteHandlers.ts +++ b/plugins/auth-node/src/oauth/createOAuthRouteHandlers.ts @@ -39,7 +39,11 @@ import { ProfileTransform, SignInResolver, } from '../types'; -import { OAuthAuthenticator, OAuthAuthenticatorResult } from './types'; +import { + OAuthAuthenticator, + OAuthAuthenticatorLogoutResult, + OAuthAuthenticatorResult, +} from './types'; import { Config, readDurationFromConfig } from '@backstage/config'; import { CookieScopeManager } from './CookieScopeManager'; @@ -280,7 +284,12 @@ export function createOAuthRouteHandlers( throw new AuthenticationError('Invalid X-Requested-With header'); } - let logoutResult: void | { logoutUrl?: string } = undefined; + const origin = req.get('origin'); + if (origin && !isOriginAllowed(origin)) { + throw new NotAllowedError(`Origin '${origin}' is not allowed`); + } + + let logoutResult: void | OAuthAuthenticatorLogoutResult = undefined; if (authenticator.logout) { const refreshToken = cookieManager.getRefreshToken(req); logoutResult = await authenticator.logout( @@ -290,7 +299,7 @@ export function createOAuthRouteHandlers( } // remove refresh token cookie if it is set - cookieManager.removeRefreshToken(res, req.get('origin')); + cookieManager.removeRefreshToken(res, origin); // remove persisted scopes await scopeManager.clear(req);