Skip to content

JWT Strategy (src/auth/strategies/jwt.strategy.ts)

Overview

The JwtStrategy implements Passport's strategy pattern for JWT authentication in the BidScript backend. It extracts and validates the JWT token from the request, verifies its signature and expiration, and extracts the user information from the payload.

Dependencies

import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { ConfigService } from '@nestjs/config';

Implementation

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    private configService: ConfigService,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: configService.get('JWT_SECRET'),
    });
  }

  async validate(payload: any) {
    // Validate payload and return user
    if (!payload.sub || !payload.username) {
      throw new UnauthorizedException('Invalid token payload');
    }

    return {
      id: payload.sub,
      username: payload.username,
      roles: payload.roles || [],
    };
  }
}

Configuration

The strategy is configured with the following options:

JwtFromRequest

ExtractJwt.fromAuthHeaderAsBearerToken()

This configures the strategy to extract the JWT token from the Authorization header using the Bearer scheme:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

IgnoreExpiration

false

This ensures that expired tokens are rejected. The strategy will throw an error if the token's expiration time has passed.

SecretOrKey

configService.get('JWT_SECRET')

The secret key used to verify the token's signature. This is loaded from environment variables using the ConfigService.

Validation Method

The validate method is called after the token has been verified by Passport. It receives the decoded JWT payload and returns a user object.

Parameters

  • payload: any - The decoded JWT payload containing user information

Returns

  • User object with ID, username, and roles

Error Handling

Throws UnauthorizedException if the payload is missing required fields or is invalid.

Integration with NestJS

The strategy is registered as a provider in the AuthModule:

@Module({
  imports: [
    PassportModule,
    JwtModule.register({/* config */}),
  ],
  providers: [
    JwtStrategy,
    // ...other providers
  ],
})
export class AuthModule {}

Usage with Guards

This strategy is used by the JwtAuthGuard to protect routes:

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
  // Custom logic for the guard
}

The guard is applied to routes using the @UseGuards() decorator:

@UseGuards(JwtAuthGuard)
@Get('protected')
getProtectedResource() {
  return { message: 'This is protected' };
}

Authentication Flow

  1. Client sends request with JWT token in Authorization header
  2. JwtStrategy extracts the token from the header
  3. Strategy verifies the token's signature using the secret key
  4. Strategy checks if the token is expired
  5. If valid, the validate method is called with the decoded payload
  6. User object is returned and attached to the request object
  7. Request is passed to the route handler

Security Considerations

  • Tokens are always validated for expiration
  • The secret key is loaded from environment variables
  • Authorization header is used for secure token transmission
  • Invalid tokens result in UnauthorizedException responses