fix(auth): remove hardcoded JWT fallback secret — fail fast on missing env var

The auth module fell back to a publicly-known secret string when JWT_SECRET
was unset, creating a critical authentication bypass risk. Both jwt.strategy.ts
and auth.module.ts now throw at startup if JWT_SECRET is missing.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-08 04:01:21 +07:00
parent 820e7e07a1
commit 402b5b6810
3 changed files with 14 additions and 3 deletions

View File

@@ -46,7 +46,7 @@ API_PORT=3000
NODE_ENV=development NODE_ENV=development
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# JWT / Auth # JWT / Auth (REQUIRED — app will not start without JWT_SECRET)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
JWT_SECRET=your_jwt_secret_change_me JWT_SECRET=your_jwt_secret_change_me
JWT_EXPIRES_IN=15m JWT_EXPIRES_IN=15m

View File

@@ -39,7 +39,13 @@ const QueryHandlers = [GetProfileHandler, GetAgentByUserIdHandler];
CqrsModule, CqrsModule,
PassportModule, PassportModule,
JwtModule.register({ JwtModule.register({
secret: process.env['JWT_SECRET'] || 'goodgo-jwt-secret-change-in-production', secret: (() => {
const secret = process.env['JWT_SECRET'];
if (!secret) {
throw new Error('JWT_SECRET environment variable is required');
}
return secret;
})(),
signOptions: { expiresIn: '15m' }, signOptions: { expiresIn: '15m' },
}), }),
], ],

View File

@@ -6,10 +6,15 @@ import { type JwtPayload } from '../services/token.service';
@Injectable() @Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) { export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() { constructor() {
const jwtSecret = process.env['JWT_SECRET'];
if (!jwtSecret) {
throw new Error('JWT_SECRET environment variable is required');
}
super({ super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false, ignoreExpiration: false,
secretOrKey: process.env['JWT_SECRET'] || 'goodgo-jwt-secret-change-in-production', secretOrKey: jwtSecret,
}); });
} }