@@ -74,7 +74,7 @@ export class SAML {
7474 case 'logout' :
7575 return this . processLogoutAction ( req , res , service ) ;
7676 case 'sloRedirect' :
77- return this . processSLORedirectAction ( req , res ) ;
77+ return this . processSLORedirectAction ( req , res , service ) ;
7878 case 'authorize' :
7979 return this . processAuthorizeAction ( res , service , samlObject ) ;
8080 case 'validate' :
@@ -384,18 +384,58 @@ export class SAML {
384384 await logOutUser ( inResponseTo ) ;
385385 } finally {
386386 res . writeHead ( 302 , {
387- Location : req . query . RelayState ,
387+ Location : Meteor . absoluteUrl ( ) ,
388388 } ) ;
389389 res . end ( ) ;
390390 }
391391 } ) ;
392392 }
393393
394- private static processSLORedirectAction ( req : IIncomingMessage , res : ServerResponse ) : void {
394+ private static processSLORedirectAction ( req : IIncomingMessage , res : ServerResponse , service : IServiceProviderOptions ) : void {
395+ const { idpSLORedirectURL } = service ;
396+ const userRedirect = req . query . redirect as string ;
397+
398+ if ( ! idpSLORedirectURL ) {
399+ res . writeHead ( 500 ) ;
400+ res . end ( 'SLO redirect not configured' ) ;
401+ return ;
402+ }
403+
404+ if ( ! userRedirect || typeof userRedirect !== 'string' ) {
405+ res . writeHead ( 400 ) ;
406+ res . end ( 'Missing redirect parameter' ) ;
407+ return ;
408+ }
409+
410+ let configuredURL : URL ;
411+ let requestURL : URL ;
412+
413+ try {
414+ configuredURL = new URL ( idpSLORedirectURL ) ;
415+ requestURL = new URL ( userRedirect ) ;
416+ } catch {
417+ res . writeHead ( 400 ) ;
418+ res . end ( 'Invalid URL format' ) ;
419+ return ;
420+ }
421+
422+ if ( configuredURL . origin !== requestURL . origin ) {
423+ res . writeHead ( 403 ) ;
424+ res . end ( 'Unauthorized redirect origin' ) ;
425+ return ;
426+ }
427+
428+ const normalizePath = ( p : string ) : string => p . replace ( / \/ + $ / , '' ) || '/' ;
429+ if ( normalizePath ( configuredURL . pathname ) !== normalizePath ( requestURL . pathname ) ) {
430+ res . writeHead ( 403 ) ;
431+ res . end ( 'Unauthorized redirect path' ) ;
432+ return ;
433+ }
434+
395435 res . writeHead ( 302 , {
396- // credentialToken here is the SAML LogOut Request that we'll send back to IDP
397- Location : req . query . redirect ,
436+ Location : requestURL . toString ( ) ,
398437 } ) ;
438+
399439 res . end ( ) ;
400440 }
401441
0 commit comments