@@ -145,11 +145,22 @@ export class GenericAuthProvider implements AuthProvider {
145
145
protected readAuthUserSetup ?: ( accessToken : string , tokenResponse : object ) => Promise < AuthUserSetup > ;
146
146
147
147
authorize ( req : express . Request , res : express . Response , next : express . NextFunction , scope ?: string [ ] ) : void {
148
- const handler = passport . authenticate ( this . getStrategy ( ) as any , {
149
- ...this . defaultStrategyOptions ,
150
- ...{ scope } ,
151
- } ) ;
152
- handler ( req , res , next ) ;
148
+ // Before the OAuth process is started, the Gitpod cookie is relaxed ot be sent on cross-site request,
149
+ // which makes possible to re-establish the session on a callback from the 3rd party service.
150
+ // Once this callback is handled, the Gitpod cookie is elevated to a `strict` one.
151
+ this . updateCookieSameSiteValue ( req , "lax" )
152
+ . then ( ( ) => {
153
+ const handler = passport . authenticate ( this . getStrategy ( ) as any , {
154
+ ...this . defaultStrategyOptions ,
155
+ ...{ scope } ,
156
+ } ) ;
157
+ handler ( req , res , next ) ;
158
+ } )
159
+ . catch ( ( err ) => {
160
+ log . error ( `(${ this . strategyName } ) Failed to store session before redirect.` , {
161
+ err,
162
+ } ) ;
163
+ } ) ;
153
164
}
154
165
155
166
protected getStrategy ( ) {
@@ -466,6 +477,16 @@ export class GenericAuthProvider implements AuthProvider {
466
477
...defaultLogPayload ,
467
478
} ) ;
468
479
480
+ try {
481
+ // When the OAuth process is done, we want to proceed with a `strict` Gitpod cookie.
482
+ // This improves the security model with Browser agents, as cross-site requests whould
483
+ // not be containing the Gitpod cookie anymore.
484
+ await this . updateCookieSameSiteValue ( request , "strict" ) ;
485
+ } catch ( error ) {
486
+ response . redirect ( this . getSorryUrl ( `Failed to save session. (${ error } )` ) ) ;
487
+ return ;
488
+ }
489
+
469
490
// Complete login
470
491
const { host, returnTo } = authFlow ;
471
492
await this . loginCompletionHandler . complete ( request , response , {
@@ -478,6 +499,19 @@ export class GenericAuthProvider implements AuthProvider {
478
499
}
479
500
}
480
501
502
+ protected async updateCookieSameSiteValue ( request : express . Request , newValue : "strict" | "lax" ) {
503
+ return new Promise ( ( resolve , reject ) => {
504
+ request . session . cookie . sameSite = newValue ;
505
+ request . session . save ( ( err ) => {
506
+ if ( err ) {
507
+ reject ( err ) ;
508
+ } else {
509
+ resolve ( undefined ) ;
510
+ }
511
+ } ) ;
512
+ } ) ;
513
+ }
514
+
481
515
protected sendCompletionRedirectWithError ( response : express . Response , error : object ) : void {
482
516
log . info ( `(${ this . strategyName } ) Send completion redirect with error` , { error } ) ;
483
517
0 commit comments