Challenges with the NestJS JWT Module

Encountering difficulties with the JWTModule in NestJS. I keep receiving this error message, even after passing the secret directly into the configuration instead of through my env file. I'm unsure of what the issue might be.

Error: secretOrPrivateKey must have a value

Here's a brief overview of how it should function:

  1. The client makes a call to /auth/login with { username: string, password: string }
  2. The LocalStrategy Guard invokes the AuthService's validateUser method, which calls ldapServices authenticateUser method and returns the user.
  3. Following that, I need to retrieve the user data from LDAP and merge it with some user data we have stored in our MongoDB database. This aspect is functioning correctly.
  4. After passing through the guard, the AuthService's login method will be called. This method should create and sign the payload with the JWT, utilizing the JwtService provided by NestJS. However, this is where the problem arises.

Below are the files along with their respective code snippets:

app.controller.ts

import { Controller, Get, Post, Request, UseGuards } from '@nestjs/common';
import { AppService } from './app.service';
import { AuthService } from './providers/auth/auth.service';
import { LocalAuthGuard } from './providers/auth/local.strategy';

@Controller()
export class AppController {
  constructor(private readonly authService: AuthService) {}

  @UseGuards(LocalAuthGuard)
  @Post('/auth/login')
  async login(@Request() req) {
    return this.authService.login(req.user);
  }
}

auth.module.ts

import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { UserModule } from './../../endpoints/user/user.module';
import { PassportModule } from '@nestjs/passport';
import { LocalStrategy } from './local.strategy';
import { JwtModule, JwtService } from '@nestjs/jwt';
import { UserService } from './../../endpoints/user/user.service';
import { LdapService } from './../ldap/ldap-service';
import { jwtConstants } from './constants';
import { JwtStrategy } from './jwt.strategy';

@Module({
  imports: [
    UserModule,
    PassportModule,
    JwtModule.register({
      secret: '2I*5f5OE9tlGIbg*3Q*C',
      signOptions: { expiresIn: '12h' },
    }),
  ],
  providers: [AuthService, LocalStrategy, LdapService],
  controllers: [AuthController],
  exports: [AuthService],
})
export class AuthModule {}

auth.service.ts

import { Injectable } from '@nestjs/common';
import { LdapService } from '../ldap/ldap-service';
import { UserService } from './../../endpoints/user/user.service';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class AuthService {
  constructor(
    private readonly ldapService: LdapService,
    private readonly userService: UserService,
    private readonly jwtService: JwtService
  ) {}

  async validateUser(username: string, pass: string): Promise<any> {
    const authenticated = await this.ldapService.authenticateUser(
      username,
      pass,
    );

    if (authenticated === true) {
      console.log(authenticated, username, pass)
      return await this.userService.getUserById(username);
    }
    return null;
  }

  async login(user: any) {
    const payload = { ...user, sub: user.accountName };
    console.log(process.env.JWT_SECRET, payload);
    return {
      access_token: this.jwtService.sign(payload),
    };
  }
}

local.strategy.ts

import { Strategy } from 'passport-local';
import { AuthGuard, PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { AuthService } from './auth.service';

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor(private authService: AuthService) {
    super();
  }

  async validate(username: string, password: string): Promise<any> {
    const user = await this.authService.validateUser(username, password);
    if (!user) throw new UnauthorizedException();
    return user;
  }
}

@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {}

I believe I'm overlooking something minor. Any assistance would be greatly appreciated.

Answer №1

Following an in-depth discussion in the comments, it was brought to light that the AuthService was being duplicated by being included in multiple providers arrays. While the JwtService has the flexibility of having @Optional() options for injection, the issue arose when it was not receiving the same options as those passed to JwtModule.register. To address this concern, the AuthModule now includes exports: [AuthService], and any module requiring the AuthService must also include imports: [AuthModule] to ensure only a single instance of AuthService is created with the correct JwtService options specified in JwtModule

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Establishing a client cookie will help deter any attempts at re-registering

Due to the inability to run server-side code, I am limited in implementing a PHP session for a registration form. Instead, I have opted to utilize a client cookie to ensure that each person can only register once with a unique email address. After reading ...

In relation to User Interface: Analyzing target tracking and studying the flow of time

Is there a way to track mouse cursor movements, button clicks, and click times to an external database using only CSS, HTML5, and Javascript? I am curious about the possibility of conducting usability studies in this manner. ...

Tips for creating an automatic interval timer reset feature

I searched for similar questions but couldn't find any that helped me. With the assistance of some kind individuals from Stack Overflow, I was able to implement an interval timer sequence on my website. This trailer automatically displays work example ...

Retrieving a Boolean Value from HTTPClient

In my authorization service, I am working on verifying the existence of a user. import { HttpClient } from "@angular/common/http"; import 'rxjs/Rx' @Injectable() export class AuthService { constructor( private http : HttpClient) {} reg ...

Querying nested arrays with mongoose

I am currently utilizing mongoose in conjunction with nodejs for executing my queries. Here are the Schemas I have established for my database model (minified, of course): var HistorySchema = new Schema({ status : String, time : Date } ...

Leveraging the power of CreateJS in partnership with Chart.js

Can anyone provide guidance on how to integrate a chartjs radar chart into a createjs canvas stage? I am attempting to use chartjs to generate the chart and then position it within the createjs stage. Any suggestions or advice would be greatly appreciate ...

Sharing on Facebook and prerendering in an angularjs application

Recently, I implemented prerender.io middleware on my Tomcat server, which is running Java webservices and an AngularJS app. The prerender service is functioning correctly, and I can see the pages being added to the list when I send a request simulating t ...

Linking a Checkbox to a Field's Value in AngularJS

I need assistance with checking/unchecking the checkbox depending on the value of the field services.Register.IsTest. If services.Register.IsTest=True, then the checkbox should be checked. Otherwise, it should remain unchecked. Here is the checkbox code: ...

Calculating the Mean of an Array in JavaScript

Greetings! I am working with an array that has the following structure: [ { group: "23", delays: [ { Station: "a", Arrival: "3", Departure: 0 }, { Station: "b", Arrival: -179, Departure: 0 }, ...

Tips for displaying a form after clicking with a delay in Angular 7

I need to update some AngularJS code for Angular 7. There is a function that displays a new form below the main one when clicked. HTML <img [hidden]="!skillsToDelete" (click)="showFormDelete(skill)" title="Delete" class="cross" src="../../../assets/i ...

Declare React component as a variable

I'm facing a simple issue that I need to solve. After creating a React app using npx create-react-app, I designed a Map component which I integrated into my view with the following code: class App extends Component { render() { return ( ...

Issue with the _.filter function in lodash library when used in a Node.js environment

My goal is to remove rows from a CSV file that already contain email addresses found in Mailchimp. Although I attempted to achieve this with a function, it seems that the number of elements returned is not accurate: async function testDeleteEmails(listID, ...

a callback may seem like it's not a function, but in reality, it is

This question might seem simple, but I'm struggling to grasp the concept of callbacks, especially in NodeJS. My issue arises when trying to retrieve data from MySQL, something that is usually straightforward in most programming languages: In my rout ...

Ways to minimize the left-hand sidebar?

Seeking a method to create a collapsible left side panel without affecting any other elements on the website. Preferably with a smooth sliding animation instead of an abrupt pop-in and out effect. Check out my website here to see the panel in question You ...

Utilizing JavaScript variable modifiers for enhanced functionality

I'm trying to find a way to perform a case-insensitive search for a variable within a string. To achieve this, I'm using the /gi modifier to ignore case sensitivity. However, the challenge arises because identifiers only accept direct strings rat ...

What is the maximum file size for an AJAX POST request?

Many queries have been raised regarding the process of uploading large strings of data via AJAX to PHP. However, most inquiries are related to uploading strings of approximately 3MB. I am looking to upload a significantly larger string. In my scenario, I ...

"Error TS2339: The property specified does not exist within type definition", located on the input field

When a user clicks a specific button, I need an input field to be focused with its text value selected entirely to allow users to replace the entire value while typing. This is the markup for the input field: <input type="text" id="descriptionField" c ...

JavaScript conditional using only conditions with ampersand operators that will evaluate only the first half of

I'm facing an issue with the conditional statement in my code. Currently, if selectedItem = null, it will set setOption = dropdownItems[0].value but won't set setPage = 1. The same problem occurs with the line below it. Can anyone provide feedbac ...

The fetch API in Javascript encounters issues when employed within an EJS file

I'm attempting to retrieve a file named files.json from the main directory of my locally hosted NodeJS backend and then display its contents in the console. <script> fetch("./files.json") .then(res => { return res.json() ...

What causes the inconsistency in time intervals in the loop?

My goal was to create a simple slider that loops through 3 images, with each image staying visible for 3 seconds before fading out and the next one fading in. However, I encountered an issue: The first image can stay for 3 seconds, but once the loop star ...