Add header API key auth to your NestJS REST API

In this tutorial, I will guide you through implementing header API key auth to your to protect your NestJS REST API endpoints

Add header API key auth to your NestJS REST API

In this tutorial, I will guide you through implementing header API key auth to your to protect your NestJS REST API endpoints. I will assume you're comfortable with NodeJS, NestJS and Typescript.

👀 Looking for basic auth? Check out my tutorial on implementing basic auth.

We're going to store a API key in plain text in our .env file, but I strongly advise you use this as a guide and use an encrypted API key instead.

Example Repo

A GIT repo with this basic auth example can be found in my Github account:

Step 1 - Create an auth module

In your application, we will need to make use of the Passport API key header Auth module. Let's go ahead and add the dependencies with NPM:

npm i passport passport-headerapikey @nestjs/passport --save

We will also need the type definitions for passport-http:

npm i @types/passport @types/passport-http --save-dev

If your application doesn't use the NestJS config module, you will need this too:

npm i @nestjs/config --save

Let's add an API key to .env file:

API_KEY=1ab2c3d4e5f61ab2c3d4e5f6

Now create a new directory in your project called auth. This will store the auth module which is responsible for authenticating our application.

Inside this file, we need to create our header API key strategy file. Inside the auth directory, create a new file called auth-header-api-key.strategy.ts and add the following to this file:

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

@Injectable()
export class HeaderApiKeyStrategy extends PassportStrategy(Strategy, 'api-key') {
    constructor(
        private readonly configService: ConfigService
    ) {
        super({ header: 'X-API-KEY', prefix: '' },
        true,
        async (apiKey, done) => {
            return this.validate(apiKey, done);
        });
    }

    public validate = (apiKey: string, done: (error: Error, data) => {}) => {
        if (this.configService.get<string>('API_KEY') === apiKey) {
            done(null, true);
        }
        done(new UnauthorizedException(), null);
    }
}

This strategy is responsible for validating the API key sent as the header X-API-KEY as part of our request from our HTTP client.

Now, still inside our auth module directory, create new file called auth.module.ts. Add the following to this file:

import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { HeaderApiKeyStrategy } from './auth-header-api-key.strategy';
import { ConfigModule } from '@nestjs/config';

@Module({
  imports: [PassportModule, ConfigModule],
  providers: [HeaderApiKeyStrategy],
})
export class AuthModule {}

This is basically all we need to do for the module. Now all that's left to do is to import this into our main application.

Step 2 - Wire the auth module into the application

Inside your main app.module.ts, include AuthModule into the main import block of the @Module() decorator:

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
// ... other import statements here
import { AuthModule } from './auth/auth.module';

@Module({
    imports: [
        ConfigModule.forRoot(),
        // ... other modules here
        AuthModule,
    ],
    controllers: [
    	// controllers here
    ],
    providers: [
    	// providers here
    ],
})
export class AppModule { }

Finally, inside our controller, we need to add the following decorator to controller methods which you want to be secured behind the basic authentication:

...
    @Get('my-endpoint')
    @UseGuards(AuthGuard('api-key'))
    findOne() {
        // do something
    }
...

Conclusion

That's it. This is what you should need to get you up and running. I strongly suggest you implement some kind of encryption, especially if you plan on storing the API keys in the database.