From f1f2fefdaba5c72b1b103c26992672fc89d402b7 Mon Sep 17 00:00:00 2001 From: Roland Schneider Date: Fri, 14 Nov 2025 17:17:42 +0100 Subject: [PATCH] logout works --- admin/src/app/auth/jwt.interceptor.ts | 4 +++- server/api.http | 7 +++++++ server/src/auth/auth.service.ts | 11 ++++++++++- server/src/auth/jwt.strategy.ts | 16 +++++++++++++--- server/src/entity/user.ts | 4 ++-- server/src/user/user.service.ts | 2 +- 6 files changed, 36 insertions(+), 8 deletions(-) diff --git a/admin/src/app/auth/jwt.interceptor.ts b/admin/src/app/auth/jwt.interceptor.ts index 605a83d..a5eb47b 100644 --- a/admin/src/app/auth/jwt.interceptor.ts +++ b/admin/src/app/auth/jwt.interceptor.ts @@ -45,7 +45,9 @@ export class JwtInterceptor implements HttpInterceptor { if (!this.isRefreshing) { this.isRefreshing = true; // Reset the refreshTokenSubject to null so that subsequent requests will wait - this.refreshTokenSubject.next(null); + // this.refreshTokenSubject.next(null); + this.refreshTokenSubject = new BehaviorSubject(null); + return this.authService.refreshToken().pipe( switchMap((token: any) => { diff --git a/server/api.http b/server/api.http index fe444d4..91fd0e4 100644 --- a/server/api.http +++ b/server/api.http @@ -13,3 +13,10 @@ Content-Type: application/json GET {{apiBaseUrl}}/users Accept: application/json Authorization: Bearer {{auth_token}} + + + +### GET request with parameter +POST {{apiBaseUrl}}/auth/logout +Accept: application/json +Authorization: Bearer {{auth_token}} diff --git a/server/src/auth/auth.service.ts b/server/src/auth/auth.service.ts index 85cb3d2..fd7a2cf 100644 --- a/server/src/auth/auth.service.ts +++ b/server/src/auth/auth.service.ts @@ -77,6 +77,15 @@ export class AuthService { } } + const jwtSecret = this.configService.get('JWT_SECRET'); + const jwtexpirationtime = this.configService.get( + 'JWT_EXPIRATION_TIME', + ); + + console.info( + 'creating. jwt secret is: ' + jwtSecret + ',' + jwtexpirationtime, + ); + // let accessToken: string, refreshToken: string; const [accessToken, refreshToken] = await Promise.all([ this.jwtService.signAsync( @@ -87,7 +96,7 @@ export class AuthService { }, { secret: this.configService.get('JWT_SECRET'), - expiresIn: this.configService.get('JWT_EXPIRATION_TIME'), + expiresIn: +this.configService.get('JWT_EXPIRATION_TIME')!, }, ), this.jwtService.signAsync( diff --git a/server/src/auth/jwt.strategy.ts b/server/src/auth/jwt.strategy.ts index 1b4fa6f..5e9222c 100644 --- a/server/src/auth/jwt.strategy.ts +++ b/server/src/auth/jwt.strategy.ts @@ -3,6 +3,7 @@ import { PassportStrategy } from '@nestjs/passport'; import { ExtractJwt, Strategy } from 'passport-jwt'; import { ConfigService } from '@nestjs/config'; import { Role } from './role.enum'; +import { Request } from 'express'; @Injectable() export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') { @@ -10,9 +11,18 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), ignoreExpiration: false, - // This is the critical fix: ensure the strategy uses the ConfigService - // to get the secret at runtime. - secretOrKey: configService.get('JWT_SECRET') as string, + // DO NOT use secretOrKey here. It causes a race condition with ConfigService. + // Instead, use secretOrKeyProvider to look up the secret dynamically + // at request time, ensuring ConfigService is ready. + secretOrKeyProvider: ( + request: Request, + rawJwtToken: any, + done: (err: any, secretOrKey?: string | Buffer) => void, + ) => { + const secretKey = this.configService.get('JWT_SECRET'); + console.info('secretKey', secretKey); + done(null, secretKey); + }, }); } diff --git a/server/src/entity/user.ts b/server/src/entity/user.ts index 9ec1168..887194d 100644 --- a/server/src/entity/user.ts +++ b/server/src/entity/user.ts @@ -25,6 +25,6 @@ export class User { @JoinTable() groups: UserGroup[]; - @Column({ nullable: true }) - hashedRefreshToken?: string; + @Column({ type: 'varchar', nullable: true }) + hashedRefreshToken: string | null; } diff --git a/server/src/user/user.service.ts b/server/src/user/user.service.ts index 6b14d5b..7f3528b 100644 --- a/server/src/user/user.service.ts +++ b/server/src/user/user.service.ts @@ -67,7 +67,7 @@ export class UserService { const hashedRefreshToken = await bcrypt.hash(refreshToken, 10); await this.usersRepository.update(id, { hashedRefreshToken }); } else { - await this.usersRepository.update(id, { hashedRefreshToken: undefined }); + await this.usersRepository.update(id, { hashedRefreshToken: null }); } } }