Search code examples
jwtheadernestjs

NestJS include WWW-Authenticate header in jwt strategy


I have a working nestjs passport JWT strategy, it returns a 401 unauthorized with invalid or missing bearer token, however, it does not set the response header WWW-Authenticate header, which I need to do for a client library that is expecting that in the header

In my AuthModule I register as so:

    JwtModule.register({
      secret: jwtConstants.secret,
      signOptions: { expiresIn: '1m' }
    })

I've also estended the JWT-strategy as follows:

import { ExtractJwt, Strategy } from 'passport-jwt';
import { jwtConstants } from './constants';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: jwtConstants.secret,
    });
  }

  validate(payload: {
    sub: string;
    email: string;
  }): { userId: string; email: string } {
    return {
      userId: payload.sub,
      email: payload.email
    };
  }
}

How can I set WWW-Authenticate header, only in the case the strategy fails / returns 401?


Solution

  • I managed to solve it with a slightly different approach, you can use Exception Filters to intercept auth failures, this worked for me, perhaps someone will find it of use:

    @Catch(HttpException)
    export class HttpExceptionFilter implements ExceptionFilter {
      constructor() {}
    
      catch(exception: HttpException, host: ArgumentsHost) {
        const ctx = host.switchToHttp();
        const response = ctx.getResponse<Response>();
        const status = exception.getStatus();
    
        if (status === 401) {
          response.setHeader(
            'WWW-Authenticate',
            'Basic realm="Access to site", charset="UTF-8"',
          );
        }
        response.status(status).json(exception.getResponse());
      }
    }
    

    Then I can implement it globally in my main.ts as follows:

    app.useGlobalFilters(new HttpExceptionFilter());