@@ -20,7 +20,8 @@ const SALT_ROUNDS = 10;
20
20
const JWT_SECRET = new TextEncoder ( ) . encode ( process . env . SECRETKEY ) ;
21
21
const JWT_COOKIE_DOMAIN = ( process . env . PRODUCTIONURLS || "" ) . split ( "," ) [ 0 ] ;
22
22
const SESSION_DEFAULT_EXPIRY_MINUTES = 60 * 24 * 7 ; // 7 days
23
- const SESSION_DEFAULT_EXPIRY_MILLISECONDS = SESSION_DEFAULT_EXPIRY_MINUTES * 60 * 1000 ;
23
+ const SESSION_DEFAULT_EXPIRY_MILLISECONDS =
24
+ SESSION_DEFAULT_EXPIRY_MINUTES * 60 * 1000 ;
24
25
25
26
const oidcBase = `https://${ process . env . OIDC_HOST } ` ;
26
27
const oidcAuth = `${ oidcBase } /cas/oidc/authorize` ;
@@ -75,17 +76,23 @@ function splitSessionJWT(sessionJWT: string) {
75
76
* @param {string } uuid - The User UUID to initialize the session for.
76
77
* @param {string } ticket - A CAS ticket ID to use for the session.
77
78
*/
78
- async function createAndAttachLocalSession ( res : Response , uuid : string , ticket ?: string ) {
79
+ async function createAndAttachLocalSession (
80
+ res : Response ,
81
+ uuid : string ,
82
+ ticket ?: string
83
+ ) {
79
84
const sessionId = uuidv4 ( ) ;
80
85
const sessionCreated = new Date ( ) ;
81
- const sessionExpiry = new Date ( sessionCreated . getTime ( ) + SESSION_DEFAULT_EXPIRY_MILLISECONDS ) ;
86
+ const sessionExpiry = new Date (
87
+ sessionCreated . getTime ( ) + SESSION_DEFAULT_EXPIRY_MILLISECONDS
88
+ ) ;
82
89
const session = new Session ( {
83
90
sessionId,
84
91
userId : uuid ,
85
92
valid : true ,
86
93
createdAt : sessionCreated ,
87
94
expiresAt : sessionExpiry ,
88
- ...ticket && { sessionTicket : ticket } ,
95
+ ...( ticket && { sessionTicket : ticket } ) ,
89
96
} ) ;
90
97
91
98
await session . save ( ) ;
@@ -153,17 +160,6 @@ async function initLogin(req: Request, res: Response) {
153
160
secure : true ,
154
161
} ;
155
162
156
- if (
157
- process . env . CONDUCTOR_DOMAIN &&
158
- process . env . CONDUCTOR_DOMAIN !== "commons.libretexts.org"
159
- ) {
160
- const authRedirectURL = `${ oidcCallbackProto } ://${ process . env . CONDUCTOR_DOMAIN } ` ;
161
- res . cookie ( "conductor_auth_redirect" , authRedirectURL , {
162
- encode : String ,
163
- httpOnly : true ,
164
- ...( process . env . NODE_ENV === "production" && prodCookieConfig ) ,
165
- } ) ;
166
- }
167
163
res . cookie ( "oidc_state" , base64State , {
168
164
encode : String ,
169
165
httpOnly : true ,
@@ -235,7 +231,7 @@ async function completeLogin(req: Request, res: Response) {
235
231
}
236
232
237
233
// Session ID (sid) from id_token will be used as the ticket identifier
238
- const idDecoded = decodeJwt ( id_token )
234
+ const idDecoded = decodeJwt ( id_token ) ;
239
235
const ticketID = idDecoded ?. sid ?. toString ( ) ;
240
236
241
237
// Verify ID token with CAS public key set
@@ -348,29 +344,28 @@ async function completeLogin(req: Request, res: Response) {
348
344
// Create local session
349
345
await createAndAttachLocalSession ( res , authUser . uuid , ticketID ) ;
350
346
351
- // Redirect user
352
- let redirectURL = req . hostname ;
353
- if ( req . cookies . conductor_auth_redirect ) {
354
- redirectURL = req . cookies . conductor_auth_redirect ;
355
- } else {
356
- const domain =
357
- process . env . NODE_ENV === "production"
358
- ? process . env . CONDUCTOR_DOMAIN
359
- : `localhost:${ process . env . CLIENT_PORT || 3000 } ` ;
360
- redirectURL = `${ oidcCallbackProto } ://${ domain } ` ;
361
- }
347
+ // Determine redirect URL
348
+ let finalRedirectURL = `${ req . protocol } ://${ req . get ( "host" ) } ` ;
349
+
350
+ // Check if redirectURI is a full URL
362
351
if ( state . redirectURI && isFullURL ( state . redirectURI ) ) {
363
- redirectURL = state . redirectURI ;
364
- } else {
352
+ finalRedirectURL = state . redirectURI ;
353
+ } else if ( state . redirectURI && ! isFullURL ( state . redirectURI ) ) {
365
354
// redirectURI is only a path or not provided
366
- redirectURL = assembleUrl ( [ redirectURL , state . redirectURI ?? "home" ] ) ;
355
+ finalRedirectURL = assembleUrl ( [ finalRedirectURL , state . redirectURI ] ) ;
356
+ } else {
357
+ // Default to home if no redirectURI is provided
358
+ finalRedirectURL = assembleUrl ( [ finalRedirectURL , "home" ] ) ;
367
359
}
368
360
369
361
if ( ! state . redirectURI && isNewMember ) {
370
- redirectURL = `${ redirectURL } ?newmember=true` ;
362
+ const _final = new URL ( finalRedirectURL ) ;
363
+ const _params = new URLSearchParams ( _final . search ) ;
364
+ _params . set ( "newmember" , "true" ) ;
365
+ finalRedirectURL = `${ _final . origin } ${ _final . pathname } ?${ _params . toString ( ) } ` ;
371
366
}
372
367
373
- return res . redirect ( redirectURL ) ;
368
+ return res . redirect ( finalRedirectURL ) ;
374
369
} catch ( e ) {
375
370
debugError ( e ) ;
376
371
return res . status ( 500 ) . send ( {
@@ -727,8 +722,8 @@ async function verifyRequest(req: Request, res: Response, next: NextFunction) {
727
722
} catch ( e : any ) {
728
723
let tokenExpired = false ;
729
724
let sessionInvalid = false ;
730
- console . log ( ' VERIFY REQUEST ERROR' )
731
- console . log ( e )
725
+ console . log ( " VERIFY REQUEST ERROR" ) ;
726
+ console . log ( e ) ;
732
727
if ( e . code === "ERR_JWT_EXPIRED" ) {
733
728
tokenExpired = true ;
734
729
} else if ( e . message === "ERR_BAD_SESSION" ) {
0 commit comments