Authentication working fine in swagger but responding as unauthorised in frontend app,though it is storing jwt token in the cookie


here is my auth.controller.ts

    import { Body, Controller, Get, Post, Req, Res, UnauthorizedException, ValidationPipe } from '@nestjs/common';
import { ApiBadRequestResponse, ApiCreatedResponse, ApiForbiddenResponse, ApiOkResponse, ApiTags, ApiUnauthorizedResponse } from '@nestjs/swagger';
import { User } from 'src/interfaces/user.interface';
import { AuthService } from './auth.service';
import { AuthCredentials } from './dto/auth-credential.dto';
import { Response,Request } from 'express';
import { JwtService } from '@nestjs/jwt';

@ApiTags('auth')
@Controller('auth')
export class AuthController {
    constructor(
        private authService: AuthService,
        private jwtService: JwtService
        ){}

    @Post('/signup')
    @ApiCreatedResponse({description: 'this response has created successfully'})
    @ApiForbiddenResponse({description: 'Forbidden'})
    signUp(@Body(ValidationPipe) authCredentials:AuthCredentials):Promise<User> {
        return this.authService.signUp(authCredentials);
    }

    @Post('/signin')
    @ApiOkResponse({description:'The resource has been successfully returned'})
    @ApiForbiddenResponse({description:'Invalid credintials'})
    async signin(@Body(ValidationPipe) authCredentials:AuthCredentials,@Res() response: Response):Promise<{accessToken:string}> {
        const token = await this.authService.signIn(authCredentials);

        response
        .cookie('access_token', token, {
            httpOnly: true,
            domain: 'localhost', // your domain here!
            expires: new Date(Date.now() + 1000 * 60 * 60 * 24),
            // expires: new Date(Date.now() + 60000 ),
        })
        .send(token);

        return token;

    }

    @Get('/cookies')
    findAll(@Req() request: Request) {
    console.log(request.cookies['access_token'].accessToken);
     // or 
    //  "request.cookies['cookieKey']"
    // or 
    // console.log(request.signedCookies);
    }


    // to verify the user's token
    @Get('/user')
    @ApiOkResponse({description:'User varified Successfully'})
    @ApiUnauthorizedResponse({description:'Unauthorised User'})
    async user(@Req() request: Request) {
        try{
            const cookies =  request.cookies['access_token']
            const cookie = cookies.accessToken 
            const data = await this.jwtService.verifyAsync(cookie)

            if(!data) {
                throw new UnauthorizedException()
            }

            const user = await this.authService.findOne(data.username)

            return user;

        }catch(e){throw new UnauthorizedException()}
    }


    // to logout by delelting the token
    @ApiOkResponse({description:'User varified Successfully'})
    @ApiBadRequestResponse({description:'login failed'})
    @Post('logout')
    async logout(@Res({passthrough: true}) response: Response) {
        response.clearCookie('access_token');

        return {
            message: 'Logged out successfully'
        }
    }
    
}

here is my auth.module.ts

import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { DatabaseModule } from 'src/database/database.module';
import { AuthController } from './auth.controller';
import { authProviders } from './auth.provider';
import { AuthService } from './auth.service';
import { AuthStrategy } from './auth.strategy';
import { JwtStrategy } from './jwt.strategy';
import { RolesGuard } from './roles.guard';
import { UserRepository } from './user.repository';

@Module({
  imports: [
    PassportModule.register({defaultStrategy:'jwt'}),
    JwtModule.register({
      secret: 'abcdefghijklmnop',
      signOptions:{
        expiresIn: 60000,
      }
    }),
    DatabaseModule],

  controllers: [AuthController],

  providers: [
    ...authProviders,
    AuthService,
    UserRepository,
    JwtStrategy,
    AuthStrategy,
    {
      provide: APP_GUARD,
      useClass: RolesGuard,
    },
    // RolesGuard
  ],

  exports: [
    JwtStrategy,
    PassportModule
  ]
  
})
export class AuthModule {}

here is jwt.strategy.ts

import { PassportStrategy } from "@nestjs/passport";
import { Strategy,ExtractJwt } from "passport-jwt"
import { Inject, Injectable, UnauthorizedException } from "@nestjs/common";
import { JwtPayload } from "../interfaces/jwt-payload.interface";
import { Model } from "mongoose";
import { User } from "src/interfaces/user.interface";


@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
    constructor(
        @Inject('USER_MODEL')
        private authModel: Model<User>,
    ){
        super({
            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken('Bearer'),
            secretOrKey: 'abcdefghijklmnop',
        })
    }

    async validate(payload: JwtPayload):Promise<User>{
        const { username } = payload ;
        const user = await this.authModel.findOne({ username }) ;

        if(!user){
            throw new UnauthorizedException()
        }

        return user
    }

    // async validate(payload: any) {
    //     return { ...payload.user };
    //   }
}

here is my user.repository.ts

import { BadRequestException, Inject, Injectable, UnauthorizedException } from "@nestjs/common";
import { Model } from "mongoose";
import { User } from "src/interfaces/user.interface";
import { AuthCredentials } from "./dto/auth-credential.dto";
var bcrypt = require('bcryptjs');


@Injectable()
export class UserRepository{
    constructor(
        @Inject('USER_MODEL')
        private authModel: Model<User>
        ){}

    async validateUser(authCredentials):Promise<boolean> {
        const username = authCredentials.username

        const userExist = await this.authModel.findOne({ username})
        if(userExist === null) {return true}
        else {return false}
    }


    async validateUserPassword(authCredentials:AuthCredentials): Promise<string> {
        const { username, password } = authCredentials;

        const user = await this.authModel.findOne({ username})
        
        if (user === null) {
            throw new UnauthorizedException('Invalid credintials')
        }else {
            const isMatch = await bcrypt.compare(password, user.password)
            if (isMatch) {
                
                return user.username

            }else {throw new BadRequestException('Invalid credintials')}
        }
    
    }


}

this is auth module. I’ve applicant, application and some other modules too which I’ve to authenticate. These are working fine in swagger but I’ve a react frontend app, Which also working partially, means it only storing the token in the cookie but whenever trying to get or access other modules they responses as 401(Unauthorised)

Source: React – Stack Overflow

November 7, 2021
Category : News
Tags: authentication | nestjs | node.js | reactjs | swagger-ui

Leave a Reply

Your email address will not be published. Required fields are marked *

Sitemap | Terms | Privacy | Cookies | Advertising

Senior Software Developer

Creator of @LzoMedia I am a backend software developer based in London who likes beautiful code and has an adherence to standards & love's open-source.