From cc337d22f22a7f36153d239141604bc3d9b9e5ae Mon Sep 17 00:00:00 2001 From: Tom Date: Thu, 19 Jun 2025 15:25:18 +0000 Subject: [PATCH] Fixed/cleaned auth validation. Added 404 response when registrations are disabled. --- .../src/asset/config/config.controller.ts | 2 +- .../src/asset/config/config.ts | 4 +- .../src/auth/auth.controller.ts | 9 +++ .../nestjs-seshat-api/src/auth/auth.module.ts | 4 +- .../src/auth/auth.service.ts | 80 +++++++++---------- ...jwt.strategy.ts => jwt-access.strategy.ts} | 4 +- 6 files changed, 57 insertions(+), 46 deletions(-) rename backend/nestjs-seshat-api/src/auth/strategies/{jwt.strategy.ts => jwt-access.strategy.ts} (92%) diff --git a/backend/nestjs-seshat-api/src/asset/config/config.controller.ts b/backend/nestjs-seshat-api/src/asset/config/config.controller.ts index b7337d4..37c6da4 100644 --- a/backend/nestjs-seshat-api/src/asset/config/config.controller.ts +++ b/backend/nestjs-seshat-api/src/asset/config/config.controller.ts @@ -4,7 +4,7 @@ import { config } from './config'; @Controller('asset') export class ConfigController { @Get('config') - async login( + async config( @Request() req, ) { return { diff --git a/backend/nestjs-seshat-api/src/asset/config/config.ts b/backend/nestjs-seshat-api/src/asset/config/config.ts index 31b8e63..d858ab9 100644 --- a/backend/nestjs-seshat-api/src/asset/config/config.ts +++ b/backend/nestjs-seshat-api/src/asset/config/config.ts @@ -1,3 +1,5 @@ export const config = { - register_enabled: false, + features: { + registration: false, + }, } \ No newline at end of file diff --git a/backend/nestjs-seshat-api/src/auth/auth.controller.ts b/backend/nestjs-seshat-api/src/auth/auth.controller.ts index 7c3ac7d..8249008 100644 --- a/backend/nestjs-seshat-api/src/auth/auth.controller.ts +++ b/backend/nestjs-seshat-api/src/auth/auth.controller.ts @@ -11,6 +11,7 @@ import { PinoLogger } from 'nestjs-pino'; import { JwtAccessGuard } from './guards/jwt-access.guard'; import { LoginDto } from './dto/login.dto'; import { AuthenticationDto } from './dto/authentication.dto'; +import { config } from 'src/asset/config/config'; @Controller('auth') export class AuthController { @@ -187,6 +188,14 @@ export class AuthController { @Res({ passthrough: true }) response: Response, @Body() body: RegisterUserDto, ) { + if (!config.features.registration) { + response.statusCode = 404; + return { + success: false, + error_message: 'Registration disabled.', + }; + } + let user: UserEntity | null; let data: AuthenticationDto | null; try { diff --git a/backend/nestjs-seshat-api/src/auth/auth.module.ts b/backend/nestjs-seshat-api/src/auth/auth.module.ts index 3bbaf5f..6d41491 100644 --- a/backend/nestjs-seshat-api/src/auth/auth.module.ts +++ b/backend/nestjs-seshat-api/src/auth/auth.module.ts @@ -6,7 +6,7 @@ import { AuthController } from './auth.controller'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { JwtModule } from '@nestjs/jwt'; import { JwtOptions } from './jwt.options'; -import { JwtStrategy } from './strategies/jwt.strategy'; +import { JwtAccessStrategy } from './strategies/jwt-access.strategy'; import { AuthRefreshService } from './auth.refresh.service'; import { TypeOrmModule } from '@nestjs/typeorm'; import { AuthRefreshTokenEntity } from './entities/auth.refresh-token.entity'; @@ -34,7 +34,7 @@ import { JwtRefreshStrategy } from './strategies/jwt-refresh.strategy'; AuthAccessService, AuthRefreshService, AuthService, - JwtStrategy, + JwtAccessStrategy, JwtRefreshStrategy, ], controllers: [AuthController] diff --git a/backend/nestjs-seshat-api/src/auth/auth.service.ts b/backend/nestjs-seshat-api/src/auth/auth.service.ts index fc0a47c..5f7ba7a 100644 --- a/backend/nestjs-seshat-api/src/auth/auth.service.ts +++ b/backend/nestjs-seshat-api/src/auth/auth.service.ts @@ -60,60 +60,60 @@ export class AuthService { accessToken: string, refreshToken: string ): Promise<{ validation: boolean, userId: UUID | null, username: string | null }> { - if (!accessToken) { - if (!refreshToken) { - return { - validation: false, - userId: null, - username: null, - } - } + let access: any = null; + let refresh: any = null; - const refresh = await this.refreshTokens.verify(refreshToken); - if (refresh.message || !refresh.exp || refresh.exp * 1000 <= new Date().getTime()) { + if (accessToken) { + access = await this.accessTokens.verify(accessToken); + if (!access.username || !access.sub) { return { validation: false, userId: null, username: null, }; } + } + + if (refreshToken) { + refresh = await this.refreshTokens.verify(refreshToken); + if (!refresh.username || !refresh.sub) { + return { + validation: false, + userId: null, + username: null, + }; + } + } + + if (accessToken && refreshToken) { + if (access.username != refresh.username || access.sub != refresh.sub) { + return { + validation: false, + userId: null, + username: null, + }; + } + } + + if (!accessToken || !access.exp || access.exp * 1000 <= new Date().getTime()) { + if (!refreshToken || !refresh.exp || refresh.exp * 1000 <= new Date().getTime()) { + // Both expired. + return { + validation: false, + userId: null, + username: null, + }; + } + + // Refresh token is still active. return { validation: null, userId: refresh.sub, username: refresh.username, }; } - const access = await this.accessTokens.verify(accessToken); - const refresh = await this.refreshTokens.verify(refreshToken); - if (!access.username || !refresh.username || access.username != refresh.username) { - return { - validation: false, - userId: null, - username: null, - }; - } - if (!access.sub || !refresh.sub || access.sub != refresh.sub) { - return { - validation: false, - userId: null, - username: null, - }; - } - if (access.message || !access.exp || access.exp * 1000 <= new Date().getTime()) { - if (refresh.message || !refresh.exp || refresh.exp * 1000 <= new Date().getTime()) { - return { - validation: false, - userId: null, - username: null, - }; - } - return { - validation: null, - userId: access.sub, - username: access.username, - }; - } + // Access still active, at least. return { validation: true, userId: access.sub, diff --git a/backend/nestjs-seshat-api/src/auth/strategies/jwt.strategy.ts b/backend/nestjs-seshat-api/src/auth/strategies/jwt-access.strategy.ts similarity index 92% rename from backend/nestjs-seshat-api/src/auth/strategies/jwt.strategy.ts rename to backend/nestjs-seshat-api/src/auth/strategies/jwt-access.strategy.ts index 211adf4..13bd1dd 100644 --- a/backend/nestjs-seshat-api/src/auth/strategies/jwt.strategy.ts +++ b/backend/nestjs-seshat-api/src/auth/strategies/jwt-access.strategy.ts @@ -6,12 +6,12 @@ import { ConfigService } from '@nestjs/config'; import { UsersService } from 'src/users/users.service'; @Injectable() -export class JwtStrategy extends PassportStrategy(Strategy, 'jwt-access') { +export class JwtAccessStrategy extends PassportStrategy(Strategy, 'jwt-access') { constructor(private users: UsersService, private config: ConfigService) { super({ jwtFromRequest: ExtractJwt.fromExtractors([ //ExtractJwt.fromAuthHeaderAsBearerToken(), - JwtStrategy.extract, + JwtAccessStrategy.extract, ]), ignoreExpiration: false, secretOrKey: config.getOrThrow('AUTH_JWT_ACCESS_TOKEN_SECRET'),