logout works

This commit is contained in:
Roland Schneider 2025-11-14 17:17:42 +01:00
parent d11b0c65e0
commit f1f2fefdab
6 changed files with 36 additions and 8 deletions

View File

@ -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<any>(null);
return this.authService.refreshToken().pipe(
switchMap((token: any) => {

View File

@ -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}}

View File

@ -77,6 +77,15 @@ export class AuthService {
}
}
const jwtSecret = this.configService.get<string>('JWT_SECRET');
const jwtexpirationtime = this.configService.get<string>(
'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<string>('JWT_SECRET'),
expiresIn: this.configService.get<StringValue>('JWT_EXPIRATION_TIME'),
expiresIn: +this.configService.get<StringValue>('JWT_EXPIRATION_TIME')!,
},
),
this.jwtService.signAsync(

View File

@ -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<string>('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<string>('JWT_SECRET');
console.info('secretKey', secretKey);
done(null, secretKey);
},
});
}

View File

@ -25,6 +25,6 @@ export class User {
@JoinTable()
groups: UserGroup[];
@Column({ nullable: true })
hashedRefreshToken?: string;
@Column({ type: 'varchar', nullable: true })
hashedRefreshToken: string | null;
}

View File

@ -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 });
}
}
}