Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement multiple passport jwt authentication strategies in Nestjs

I have an existing authentication for users which is already working fine. The token for user authentication expires within an hour.

I want to implement another separate authentication strategy a third API that is consuming my Nestjs API. There are separate endpoints for the third-party API, the token should expire with 24 hours. The API has to stay connected to my app for 24 hours.

I don't mind using additional package to achieve this.

I also need to create a guard called thirdParty Guard so that the 3rd part API alone will have access to that endpoint.

This is my jwt.strategy.ts

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
    constructor(private authService: AuthService) {
        super({
            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
            ignoreExpiration: false,
            secretOrKey: process.env.SECRETKEY
        });
    }

    async validate(payload: any, done: VerifiedCallback) {
        const user = await this.authService.validateUser(payload);
        if (!user) {
            return done(
                new HttpException('Unauthorised access', HttpStatus.UNAUTHORIZED),
                false,
            );
        }
        //return user;
        return done(null, user, payload.iat)
    }
}

ApiKey.strategy.ts

@Injectable()
export class ApiKeyStrategy extends PassportStrategy(HeaderAPIKeyStrategy) {
    constructor(private authService: AuthService) {
        super({
            header: 'api_key',
            prefix: ''
        }, true,
            (apikey: string, done: any, req: any, next: () => void) => {
                const checkKey = this.authService.validateApiKey(apikey);
                if (!checkKey) {
                    return done(
                        new HttpException('Unauthorized access, verify the token is correct', HttpStatus.UNAUTHORIZED),
                        false,
                    );
                }
                return done(null, true, next);
            });
    }
}

and this is the auth.service.ts

@Injectable()
export class AuthService {
    constructor(private userService: UserService) { }

    async signPayLoad(payload: any) {
        return sign(payload, process.env.SECRETKEY, { expiresIn: '1h' });

    }

    async validateUser(payload: any) {
        const returnuser = await this.userService.findByPayLoad(payload);
        return returnuser;
    }

    validateApiKey(apiKey: string) {
        const keys = process.env.API_KEYS;
        const apiKeys = keys.split(',');
        return apiKeys.find(key => apiKey === key);
    }
}
like image 879
techstack Avatar asked Jul 01 '20 07:07

techstack


People also ask

Which is better JWT or passport?

JSON Web Token and Passport can be primarily classified as "User Management and Authentication" tools. JSON Web Token and Passport are both open source tools. It seems that Passport with 15.9K GitHub stars and 936 forks on GitHub has more adoption than JSON Web Token with 2.59K GitHub stars and 259 GitHub forks.

Can I use passport with JWT?

A Passport strategy for authenticating with a JSON Web Token. This module lets you authenticate endpoints using a JSON web token. It is intended to be used to secure RESTful endpoints without sessions.


1 Answers

With the above setup, If you are using Passport-HeaderAPIKey then try adding headerapikey in the Guard. The below code worked for me.

Ref: NestJS extending guard

import { ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { AuthGuard as NestAuthGuard } from '@nestjs/passport';

@Injectable()
export class AuthGuard extends NestAuthGuard(['jwt', 'headerapikey']) {
  constructor(private readonly reflector: Reflector) {
    super();
  }

  canActivate(context: ExecutionContext) {
    const isPublic = this.reflector.getAllAndOverride<boolean>('isPublic', [
      context.getHandler(),
      context.getClass(),
    ]);

    if (isPublic) {
      return true;
    }

    return super.canActivate(context);
  }
}
like image 87
Selvam Kumar Avatar answered Oct 09 '22 13:10

Selvam Kumar