Introduction: Why Protect API Routes?

Welcome back! In the last two lessons, you learned how to:

  • Register users securely (with hashed passwords).
  • Let users log in and receive a JWT (JSON Web Token).

Now, it’s time to put those JWTs to work by protecting API routes.

In real-world applications, not every endpoint should be open to everyone. For example:

  • Public: listing books (anyone can view).
  • Private: creating, updating, or deleting books (requires login).

In this unit, you’ll enforce authentication only: a valid JWT is required to access certain routes.
Authorization (like restricting book creation to admins) comes later in the next unit.

Recap: Where We Are Now

So far, you have:

  • A registration system that hashes and stores user passwords.
  • A login system that validates credentials and returns a signed JWT.
  • A JWT payload that contains the user’s ID (sub) and role.

Now you’ll enforce authentication by requiring a valid JWT for protected endpoints.

Understanding AuthGuards in NestJS

NestJS provides a powerful concept called guards. Think of them as security checkpoints for routes.
A guard decides whether a request is allowed to continue to the route handler.

For authentication, NestJS provides the @nestjs/passport package, which integrates with Passport strategies (like JWT).
By using AuthGuard('jwt'), you can easily protect any route:

  • If the request includes a valid token, the guard lets it through.
  • If the token is missing, expired, or invalid, the guard blocks the request with a 401 Unauthorized error.
Implementing JWT Authentication with AuthGuard

Here’s how we apply JWT-based protection in the controllers:

// src/reading/reading.controller.ts
@Patch('progress')
@UseGuards(AuthGuard('jwt'))
updateProgress(@Body() updateProgressDto: UpdateProgressDto) {
  const session = this.readingService.updateProgress(updateProgressDto);
  return { success: true, data: session };
}

// src/books/books.controller.ts
@Post()
@UseGuards(AuthGuard('jwt'))
create(@Body() createBookDto: CreateBookDto) {
  const book = this.booksService.create(createBookDto);
  return { success: true, data: book };
}

How it works:

  • @UseGuards(AuthGuard('jwt')) tells NestJS to use the JWT strategy for this route.
  • The guard checks the Authorization header for a Bearer token:
Authorization: Bearer <token>
  • The token is verified using the secret key from JwtModule.
  • If valid → the request continues.
  • If invalid/missing → NestJS returns 401 Unauthorized automatically.

This makes authentication almost effortless to enforce.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal