Introduction to Endpoint Security

Welcome to the lesson on securing endpoints with JWT Guards in your NestJS application. In our previous lessons, we laid a solid foundation for user authentication. We explored creating users with encrypted passwords using bcrypt, and then we progressed to integrating JSON Web Tokens (JWT) for authentication. Now, we'll focus on safeguarding API endpoints using Guards in NestJS. This step is crucial for ensuring that sensitive resources are protected and only accessible to authenticated users. By the end of this lesson, you'll be able to implement a JWT-based security layer for your ToDo app's endpoints.

Creating a NestJS Auth Guard

Guards in NestJS act as middleware, determining if a request can proceed upon its received verification. We’ll create an AuthGuard that uses JWTs to ensure that only authenticated requests gain access:

Step-by-step Breakdown:
  1. Define the AuthGuard:

  2. Explanation:

    • The AuthGuard checks each incoming request for a JWT in the Authorization header.
    • If present and valid, it attaches the user payload from the JWT to the request object.
    • If not, it throws an UnauthorizedException, blocking access to the endpoint.

This Guard is a crucial part of your security strategy, ensuring only authenticated requests can reach certain endpoints.

Secure all routes with the AuthGuard

In a NestJS application, securing all routes by default ensures that only authenticated users can access the application's resources. By integrating the AuthGuard at the module level, we can enforce this security measure across all endpoints, except those explicitly marked as public.

In this configuration, the AuthGuard is added to the providers array, allowing it to be automatically injected where needed. The JwtService is also included since it's a dependency required by the AuthGuard for verifying tokens.

app/src/auth/auth.module.ts

After implementing these changes, all routes within the application will require a valid JWT token. This pattern ensures a strong security stance by default, minimizing potential unauthorized access to application endpoints.

Implementing the Public Decorator

In some cases, you’ll want to allow public access to specific routes, like registration or login. We’ll implement a Public decorator that allows you to mark these routes as exceptions.

Code Example:
Explanation:
  • Public is a custom decorator using SetMetadata.
  • It marks certain endpoints as public by associating metadata with them to be read by the guard (next).
  • NestJS guards can read this metadata to selectively allow public access.
Updating the AuthGuard to allow public routes

Now, we must check for the metadata that was injected with the @Public decorator. If it exists, we allow the request to go through.

app/src/auth/auth.guard.ts

Explanation:
  • isPublic will check for metadata on Controllers or Controller Handlers.
  • If we detect the public metadata (via IS_PUBLIC_KEY), we let the request through.
  • Otherwise we check for a valid JWT as we did in the previous example.
Example: Allowing the registration and login methods to be public

Most of our API can be protected by the AuthGuard and require a JWT token. However, that is not true for the auth/register and auth/login routes! You don't have a token if you haven't registered or logged-in yet. We can use our @Public() decorator on our routes:

Explanation:
  • @Public(): The @Public() decorator sets the isPublic value to true in the metadata. This allows these routes to be executed without a token.
Using the JWT token to access protected routes

Once authentication is set up in your NestJS application, users will receive a JWT token upon successful login. This token must be included in the HTTP headers for requests to access protected routes. Here's how a consumer can send the JWT token using a sample script.

Sample Request Script

In this example, we demonstrate how to utilize the JWT token in an HTTP request header using a tool like axios in a JavaScript environment:

send_request.ts

Explanation:
  • The createTodo and getTodo functions require an access_token that was recieved by logging in to the API.
  • The access token is passed in as a header to the request.
  • Authorization: Bearer ${token}`` is the standard header to set for token in HTTP.
Lesson Summary and Preparing for Practice

In this lesson, you've learned to secure endpoints using JWT Guards in a NestJS application. We've covered JWT components, authentication with AuthGuard, and marking specific endpoints as public using the Public decorator. These skills are critical to ensuring that only authenticated users can access sensitive data or operations within your application.

Next, you’ll have the opportunity to apply these skills through hands-on practice exercises. Remember, securing API endpoints is a vital real-world skill that enhances the security and integrity of web applications. Great job reaching this far, and keep up the excellent work!

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