@@ -20,7 +20,7 @@ import { HostContextProvider } from "./host-context-provider";
2020import { SignInJWT } from "./jwt" ;
2121import { NonceService } from "./nonce-service" ;
2222import { getFeatureFlagEnableNonceValidation , getFeatureFlagEnableStrictAuthorizeReturnTo } from "../util/featureflags" ;
23- import { validateLoginReturnToUrl , validateAuthorizeReturnToUrl , safeRedirect } from "../express-util" ;
23+ import { validateLoginReturnToUrl , validateAuthorizeReturnToUrl , safeFragmentRedirect } from "../express-util" ;
2424
2525@injectable ( )
2626export class Authenticator {
@@ -93,7 +93,7 @@ export class Authenticator {
9393 pathname : req . path ,
9494 search : new URL ( req . url , this . config . hostUrl . url ) . search ,
9595 } ) ;
96- safeRedirect ( res , baseUrl . toString ( ) ) ;
96+ safeFragmentRedirect ( res , baseUrl . toString ( ) ) ;
9797 return ;
9898 }
9999
@@ -185,12 +185,14 @@ export class Authenticator {
185185 let returnToParam : string | undefined = req . query . returnTo ?. toString ( ) ;
186186 if ( returnToParam ) {
187187 log . info ( `Stored returnTo URL: ${ returnToParam } ` , { "login-flow" : true } ) ;
188-
189- // Validate returnTo URL against allowlist for login API
190- if ( ! validateLoginReturnToUrl ( returnToParam , this . config . hostUrl ) ) {
191- log . warn ( `Invalid returnTo URL rejected for login: ${ returnToParam } ` , { "login-flow" : true } ) ;
192- safeRedirect ( res , this . getSorryUrl ( `Invalid return URL.` ) ) ;
193- return ;
188+ const isStrictAuthorizeValidationEnabled = await getFeatureFlagEnableStrictAuthorizeReturnTo ( ) ;
189+ if ( isStrictAuthorizeValidationEnabled ) {
190+ // Validate returnTo URL against allowlist for login API
191+ if ( ! validateLoginReturnToUrl ( returnToParam , this . config . hostUrl ) ) {
192+ log . warn ( `Invalid returnTo URL rejected for login: ${ returnToParam } ` , { "login-flow" : true } ) ;
193+ safeFragmentRedirect ( res , this . getSorryUrl ( `Invalid return URL.` ) ) ;
194+ return ;
195+ }
194196 }
195197 }
196198 // returnTo defaults to workspaces url
@@ -202,7 +204,7 @@ export class Authenticator {
202204 const authProvider = host && ( await this . getAuthProviderForHost ( host ) ) ;
203205 if ( ! host || ! authProvider ) {
204206 log . info ( `Bad request: missing parameters.` , { "login-flow" : true } ) ;
205- safeRedirect ( res , this . getSorryUrl ( `Bad request: missing parameters.` ) ) ;
207+ safeFragmentRedirect ( res , this . getSorryUrl ( `Bad request: missing parameters.` ) ) ;
206208 return ;
207209 }
208210 // Logins with organizational Git Auth is not permitted
@@ -211,12 +213,12 @@ export class Authenticator {
211213 "authorize-flow" : true ,
212214 ap : authProvider . info ,
213215 } ) ;
214- safeRedirect ( res , this . getSorryUrl ( `Login with "${ host } " is not permitted.` ) ) ;
216+ safeFragmentRedirect ( res , this . getSorryUrl ( `Login with "${ host } " is not permitted.` ) ) ;
215217 return ;
216218 }
217219 if ( this . config . disableDynamicAuthProviderLogin && ! authProvider . params . builtin ) {
218220 log . info ( `Auth Provider is not allowed.` , { ap : authProvider . info } ) ;
219- safeRedirect ( res , this . getSorryUrl ( `Login with ${ authProvider . params . host } is not allowed.` ) ) ;
221+ safeFragmentRedirect ( res , this . getSorryUrl ( `Login with ${ authProvider . params . host } is not allowed.` ) ) ;
220222 return ;
221223 }
222224
@@ -226,7 +228,7 @@ export class Authenticator {
226228 "login-flow" : true ,
227229 ap : authProvider . info ,
228230 } ) ;
229- safeRedirect ( res , this . getSorryUrl ( `Login with "${ host } " is not permitted.` ) ) ;
231+ safeFragmentRedirect ( res , this . getSorryUrl ( `Login with "${ host } " is not permitted.` ) ) ;
230232 return ;
231233 }
232234
@@ -248,7 +250,7 @@ export class Authenticator {
248250 const user = req . user ;
249251 if ( ! req . isAuthenticated ( ) || ! User . is ( user ) ) {
250252 log . info ( `User is not authenticated.` ) ;
251- safeRedirect ( res , this . getSorryUrl ( `Not authenticated. Please login.` ) ) ;
253+ safeFragmentRedirect ( res , this . getSorryUrl ( `Not authenticated. Please login.` ) ) ;
252254 return ;
253255 }
254256 const returnTo : string = req . query . returnTo ?. toString ( ) || this . config . hostUrl . asDashboard ( ) . toString ( ) ;
@@ -258,20 +260,20 @@ export class Authenticator {
258260
259261 if ( ! host || ! authProvider ) {
260262 log . warn ( `Bad request: missing parameters.` ) ;
261- safeRedirect ( res , this . getSorryUrl ( `Bad request: missing parameters.` ) ) ;
263+ safeFragmentRedirect ( res , this . getSorryUrl ( `Bad request: missing parameters.` ) ) ;
262264 return ;
263265 }
264266
265267 try {
266268 await this . userAuthentication . deauthorize ( user , authProvider . authProviderId ) ;
267- safeRedirect ( res , returnTo ) ;
269+ safeFragmentRedirect ( res , returnTo ) ;
268270 } catch ( error ) {
269271 next ( error ) ;
270272 log . error ( `Failed to disconnect a provider.` , error , {
271273 host,
272274 userId : user . id ,
273275 } ) ;
274- safeRedirect (
276+ safeFragmentRedirect (
275277 res ,
276278 this . getSorryUrl (
277279 `Failed to disconnect a provider: ${ error && error . message ? error . message : "unknown reason" } ` ,
@@ -284,12 +286,12 @@ export class Authenticator {
284286 const user = req . user ;
285287 if ( ! req . isAuthenticated ( ) || ! User . is ( user ) ) {
286288 log . info ( `User is not authenticated.` , { "authorize-flow" : true } ) ;
287- safeRedirect ( res , this . getSorryUrl ( `Not authenticated. Please login.` ) ) ;
289+ safeFragmentRedirect ( res , this . getSorryUrl ( `Not authenticated. Please login.` ) ) ;
288290 return ;
289291 }
290292 if ( user . id === BUILTIN_INSTLLATION_ADMIN_USER_ID ) {
291293 log . info ( `Authorization is not permitted for admin user.` ) ;
292- safeRedirect (
294+ safeFragmentRedirect (
293295 res ,
294296 this . getSorryUrl ( `Authorization is not permitted for admin user. Please login with a user account.` ) ,
295297 ) ;
@@ -303,24 +305,22 @@ export class Authenticator {
303305
304306 if ( ! returnToParam || ! host || ! authProvider ) {
305307 log . info ( `Bad request: missing parameters.` , { "authorize-flow" : true } ) ;
306- safeRedirect ( res , this . getSorryUrl ( `Bad request: missing parameters.` ) ) ;
308+ safeFragmentRedirect ( res , this . getSorryUrl ( `Bad request: missing parameters.` ) ) ;
307309 return ;
308310 }
309311
310312 // Validate returnTo URL against allowlist for authorize API
311313 const isStrictAuthorizeValidationEnabled = await getFeatureFlagEnableStrictAuthorizeReturnTo ( ) ;
312- const isValidReturnTo = isStrictAuthorizeValidationEnabled
313- ? validateAuthorizeReturnToUrl ( returnToParam , this . config . hostUrl )
314- : validateLoginReturnToUrl ( returnToParam , this . config . hostUrl ) ;
315-
316- if ( ! isValidReturnTo ) {
317- const validationType = isStrictAuthorizeValidationEnabled ? "strict authorize" : "login fallback" ;
318- log . warn ( `Invalid returnTo URL rejected for authorize (${ validationType } ): ${ returnToParam } ` , {
319- "authorize-flow" : true ,
320- strictValidation : isStrictAuthorizeValidationEnabled ,
321- } ) ;
322- safeRedirect ( res , this . getSorryUrl ( `Invalid return URL.` ) ) ;
323- return ;
314+ if ( isStrictAuthorizeValidationEnabled ) {
315+ const isValidReturnTo = validateAuthorizeReturnToUrl ( returnToParam , this . config . hostUrl ) ;
316+ if ( ! isValidReturnTo ) {
317+ log . warn ( `Invalid returnTo URL rejected for authorize` , {
318+ "authorize-flow" : true ,
319+ returnToParam,
320+ } ) ;
321+ safeFragmentRedirect ( res , this . getSorryUrl ( `Invalid return URL.` ) ) ;
322+ return ;
323+ }
324324 }
325325
326326 const returnTo = returnToParam ;
@@ -333,7 +333,7 @@ export class Authenticator {
333333 "authorize-flow" : true ,
334334 ap : authProvider . info ,
335335 } ) ;
336- safeRedirect ( res , this . getSorryUrl ( `Authorization with "${ host } " is not permitted.` ) ) ;
336+ safeFragmentRedirect ( res , this . getSorryUrl ( `Authorization with "${ host } " is not permitted.` ) ) ;
337337 return ;
338338 }
339339 }
@@ -344,7 +344,7 @@ export class Authenticator {
344344 "authorize-flow" : true ,
345345 ap : authProvider . info ,
346346 } ) ;
347- safeRedirect ( res , this . getSorryUrl ( `Authorization with "${ host } " is not permitted.` ) ) ;
347+ safeFragmentRedirect ( res , this . getSorryUrl ( `Authorization with "${ host } " is not permitted.` ) ) ;
348348 return ;
349349 }
350350
@@ -356,7 +356,7 @@ export class Authenticator {
356356 "authorize-flow" : true ,
357357 ap : authProvider . info ,
358358 } ) ;
359- safeRedirect ( res , this . getSorryUrl ( `Authorization with "${ host } " is not permitted.` ) ) ;
359+ safeFragmentRedirect ( res , this . getSorryUrl ( `Authorization with "${ host } " is not permitted.` ) ) ;
360360 return ;
361361 }
362362 }
0 commit comments