diff --git a/idp/src/model/entity/user.entity.ts b/idp/src/model/entity/user.entity.ts index b8f509f..d823895 100644 --- a/idp/src/model/entity/user.entity.ts +++ b/idp/src/model/entity/user.entity.ts @@ -57,6 +57,10 @@ export class User { @ManyToMany(() => Client, (client) => client.admins) clients?: Client[]; + @Exclude() + @Column({ type: 'int', default: 0 }) + pwRevision?: number; // wird hochgezählt wenn das PW geändert wird. somit kann der Token invalid gesetzt werden. + accessToken?: string; refreshToken?: string; session_key?: string; diff --git a/idp/src/model/interface/index.ts b/idp/src/model/interface/index.ts index 644d822..7cf0ac0 100644 --- a/idp/src/model/interface/index.ts +++ b/idp/src/model/interface/index.ts @@ -1,3 +1,4 @@ export * from './authenticated.request'; export * from './logger.interface'; export * from './mailconfig.interface'; +export * from './payload.interface'; diff --git a/idp/src/model/interface/payload.interface.ts b/idp/src/model/interface/payload.interface.ts new file mode 100644 index 0000000..99f5f54 --- /dev/null +++ b/idp/src/model/interface/payload.interface.ts @@ -0,0 +1,18 @@ +export interface IAccessPayload { + username: string; + firstName: string; + lastName: string; + id: string; + iss: string; + aud: string; + iat: number; + exp: number; +} + +export interface IRefreshPayload { + type: string; + id: string; + token_revision: number; + iat: number; + exp: number; +} diff --git a/idp/src/shared/users.service.ts b/idp/src/shared/users.service.ts index 632ae92..00a60c8 100644 --- a/idp/src/shared/users.service.ts +++ b/idp/src/shared/users.service.ts @@ -15,6 +15,8 @@ import { AuthorizationCodeRepository, AuthorizationCode, ActivityLogRepository, + IAccessPayload, + IRefreshPayload, } from 'src/model'; import { CustomLogger } from './logger/custom.logger'; @@ -126,7 +128,6 @@ export class UsersService { if (getUserAccessToken) { user.accessToken = this.createAccessToken(user); user.refreshToken = this.createRefreshToken(user); - console.log(this.jwtService.verify(user.accessToken)) return user; } @@ -206,25 +207,30 @@ export class UsersService { { type: 'refresh', id: user.id, + token_revision: user.pwRevision, }, { expiresIn: '365d' }, ); } async getNewAccessToken(refreshToken: string) { - const payload = this.jwtService.verify(refreshToken); + const payload: IRefreshPayload = this.jwtService.verify(refreshToken); if (payload.type !== 'refresh') { this.logger.error(`Token ${refreshToken} is not a refresh token`); throw new HttpException('Invalid token', 401); } const user = await this.userRepo.findById(payload.id); - if (!user) { + if ( + !user || + payload['token_revision'] == undefined || + payload['token_revision'] != user.pwRevision + ) { this.logger.error(`User ${payload.id} not found for refresh token`); throw new HttpException('Invalid token', 401); } const token = this.createAccessToken(user); - const pay = this.jwtService.decode(token); + const pay: IAccessPayload = this.jwtService.decode(token); const result = { access_token: token, expires_in: pay.exp - pay.iat, @@ -238,7 +244,7 @@ export class UsersService { try { const decoded = this.jwtService.verify(token); this.activityRepo.logAccessTokenVerification(); - console.log(decoded) + console.log(decoded, '-'); return decoded; } catch (e) { this.logger.error(`Token ${token} is invalid. Error: ${e.message}`); @@ -305,6 +311,7 @@ export class UsersService { if (savedCode && savedCode.user) { const hashedPassword = await bcrypt.hash(dto.password, 10); savedCode.user.password = hashedPassword; + savedCode.user.pwRevision += 1; await this.userRepo.save(savedCode.user); await this.resetPwRepo.remove(savedCode); await this.sessionRepo.delete({ user: { id: savedCode.user.id } });