@@ -10,11 +10,17 @@ const PORT = 9999;
1010// Configuration from environment
1111const USERNAME = process . env . USER || '' ;
1212const PASSWORD = process . env . PASSWORD || '' ;
13+ const AUTH_HASH = process . env . AUTH_HASH || '' ;
1314const SESSION_DURATION_HOURS = parseInt ( process . env . SESSION_DURATION_HOURS || '720' , 10 ) ;
1415const SESSION_DURATION_MS = SESSION_DURATION_HOURS * 60 * 60 * 1000 ;
1516
17+ // Generate password hash for session validation
18+ // When password changes (container restart), password-based sessions become invalid
19+ const PASSWORD_HASH = crypto . createHash ( 'sha256' ) . update ( PASSWORD + USERNAME ) . digest ( 'hex' ) ;
20+
1621// In-memory session store
17- // Format: { sessionId: { expires: timestamp } }
22+ // Format: { sessionId: { expires: timestamp, passwordHash?: string, authHash?: string } }
23+ // Sessions can be authenticated via password OR auth hash
1824const sessions = { } ;
1925
2026// Generate secure random session ID
@@ -123,7 +129,7 @@ app.get('/login', (req, res) => {
123129<body>
124130 <div class="container">
125131 <h1>🔒 Login Required</h1>
126- <form method="POST" action="/auth/login">
132+ <form method="POST" action="/nhl- auth/login">
127133 <div class="form-group">
128134 <label>Username</label>
129135 <input type="text" name="username" required autofocus>
@@ -157,7 +163,7 @@ app.get('/login', (req, res) => {
157163} ) ;
158164
159165// Handle login submission
160- app . post ( '/auth/login' , async ( req , res ) => {
166+ app . post ( '/nhl- auth/login' , async ( req , res ) => {
161167 const { username, password, redirect } = req . body ;
162168 const startTime = Date . now ( ) ;
163169
@@ -168,7 +174,8 @@ app.post('/auth/login', async (req, res) => {
168174 // Create session
169175 const sessionId = generateSessionId ( ) ;
170176 sessions [ sessionId ] = {
171- expires : Date . now ( ) + SESSION_DURATION_MS
177+ expires : Date . now ( ) + SESSION_DURATION_MS ,
178+ passwordHash : PASSWORD_HASH
172179 } ;
173180
174181 console . log ( `[Auth Service] Login successful for user: ${ username } ` ) ;
@@ -197,14 +204,34 @@ app.post('/auth/login', async (req, res) => {
197204} ) ;
198205
199206// Auth check endpoint (called by nginx auth_request)
200- app . get ( '/auth/check' , ( req , res ) => {
207+ app . get ( '/nhl- auth/check' , ( req , res ) => {
201208 // Check for existing session first
202209 let sessionId = req . cookies . nginxhashlock_session ;
203210
204- if ( sessionId && sessions [ sessionId ] && sessions [ sessionId ] . expires > Date . now ( ) ) {
205- // Valid session exists
206- console . log ( `[Auth Service] Auth check passed via session (${ sessionId . substring ( 0 , 8 ) } ...)` ) ;
207- return res . status ( 200 ) . send ( 'OK' ) ;
211+ if ( sessionId && sessions [ sessionId ] ) {
212+ const session = sessions [ sessionId ] ;
213+
214+ // Check if session is expired
215+ if ( session . expires < Date . now ( ) ) {
216+ console . log ( `[Auth Service] Auth check failed: Session expired (${ sessionId . substring ( 0 , 8 ) } ...)` ) ;
217+ delete sessions [ sessionId ] ;
218+ // Continue to check other auth methods
219+ }
220+ // Check if credentials are still valid
221+ else {
222+ // Session is valid if EITHER password hash OR auth hash matches
223+ const passwordValid = session . passwordHash && session . passwordHash === PASSWORD_HASH ;
224+ const authHashValid = session . authHash && session . authHash === AUTH_HASH ;
225+
226+ if ( passwordValid || authHashValid ) {
227+ console . log ( `[Auth Service] Auth check passed via session (${ sessionId . substring ( 0 , 8 ) } ...)` ) ;
228+ return res . status ( 200 ) . send ( 'OK' ) ;
229+ } else {
230+ console . log ( `[Auth Service] Auth check failed: Credentials changed, invalidating session (${ sessionId . substring ( 0 , 8 ) } ...)` ) ;
231+ delete sessions [ sessionId ] ;
232+ // Continue to check other auth methods
233+ }
234+ }
208235 }
209236
210237 // No valid session - check if hash parameter is valid
@@ -219,7 +246,8 @@ app.get('/auth/check', (req, res) => {
219246 if ( ! sessionId || ! sessions [ sessionId ] ) {
220247 sessionId = generateSessionId ( ) ;
221248 sessions [ sessionId ] = {
222- expires : Date . now ( ) + SESSION_DURATION_MS
249+ expires : Date . now ( ) + SESSION_DURATION_MS ,
250+ authHash : AUTH_HASH
223251 } ;
224252
225253 console . log ( `[Auth Service] Session created for hash auth: ${ sessionId . substring ( 0 , 8 ) } ... (expires in ${ SESSION_DURATION_HOURS } h)` ) ;
@@ -258,36 +286,57 @@ app.get('/auth/check', (req, res) => {
258286 return res . status ( 401 ) . send ( 'Unauthorized' ) ;
259287 }
260288
289+ // Check if password has changed
290+ if ( session . passwordHash && session . passwordHash !== PASSWORD_HASH ) {
291+ console . log ( `[Auth Service] Auth check failed: Password changed, invalidating session (${ sessionId . substring ( 0 , 8 ) } ...)` ) ;
292+ delete sessions [ sessionId ] ;
293+ return res . status ( 401 ) . send ( 'Unauthorized' ) ;
294+ }
295+
261296 // Session is valid
262297 console . log ( `[Auth Service] Auth check passed via session (${ sessionId . substring ( 0 , 8 ) } ...)` ) ;
263298 res . status ( 200 ) . send ( 'OK' ) ;
264299} ) ;
265300
266301// Establish session endpoint (for hash authentication to set cookies properly)
267- app . get ( '/auth/establish-session' , ( req , res ) => {
302+ app . get ( '/nhl- auth/establish-session' , ( req , res ) => {
268303 // Check if hash parameter is valid
269304 if ( process . env . AUTH_HASH ) {
270305 const hash = req . query . hash ;
271- const returnTo = req . query . return_to || '/' ;
306+ let returnTo = req . query . return_to || '/' ;
307+
308+ // Strip hash parameter from return URL to prevent redirect loop
309+ returnTo = returnTo . replace ( / [ ? & ] h a s h = [ ^ & ] + ( & | $ ) / , ( match , p1 ) => p1 === '&' ? '&' : '?' ) . replace ( / [ ? & ] $ / , '' ) . replace ( / \? $ / , '' ) || '/' ;
272310
273311 if ( hash && hash === process . env . AUTH_HASH ) {
274312 // Check if session already exists
275313 let sessionId = req . cookies . nginxhashlock_session ;
276314
277- if ( sessionId && sessions [ sessionId ] && sessions [ sessionId ] . expires > Date . now ( ) ) {
278- // Valid session already exists
279- console . log ( `[Auth Service] Session already valid: ${ sessionId . substring ( 0 , 8 ) } ...` ) ;
280- // Redirect back if requested
281- if ( req . query . return_to ) {
282- return res . redirect ( returnTo ) ;
315+ if ( sessionId && sessions [ sessionId ] ) {
316+ const session = sessions [ sessionId ] ;
317+ // Check if session is valid (not expired and credentials are still valid)
318+ const passwordValid = session . passwordHash && session . passwordHash === PASSWORD_HASH ;
319+ const authHashValid = session . authHash && session . authHash === AUTH_HASH ;
320+
321+ if ( session . expires > Date . now ( ) && ( passwordValid || authHashValid ) ) {
322+ // Valid session already exists
323+ console . log ( `[Auth Service] Session already valid: ${ sessionId . substring ( 0 , 8 ) } ...` ) ;
324+ // Redirect back if requested
325+ if ( req . query . return_to ) {
326+ return res . redirect ( returnTo ) ;
327+ }
328+ return res . status ( 200 ) . json ( { status : 'ok' , message : 'Session already valid' } ) ;
329+ } else {
330+ // Session expired or password changed, delete it
331+ delete sessions [ sessionId ] ;
283332 }
284- return res . status ( 200 ) . json ( { status : 'ok' , message : 'Session already valid' } ) ;
285333 }
286334
287335 // Create new session
288336 sessionId = generateSessionId ( ) ;
289337 sessions [ sessionId ] = {
290- expires : Date . now ( ) + SESSION_DURATION_MS
338+ expires : Date . now ( ) + SESSION_DURATION_MS ,
339+ authHash : AUTH_HASH
291340 } ;
292341
293342 console . log ( `[Auth Service] Session established via hash: ${ sessionId . substring ( 0 , 8 ) } ... (expires in ${ SESSION_DURATION_HOURS } h)` ) ;
0 commit comments