0
votes

I'm trying to implement a nestjs authentication and authorization for a tasks app

I'm using JWT strategy with passport

But I Cannot implement logout method

I tried

@Get('/logout')
logout(@Request() req) {
    req.logout();
}

it returns 200 but then I can still get data with the token for the same user that just logged out

my jwt-strategy file

import { Injectable, UnauthorizedException } from "@nestjs/common";
import { PassportStrategy } from '@nestjs/passport';
import { Strategy, ExtractJwt } from 'passport-jwt';
import { InjectRepository } from "@nestjs/typeorm";
import { UserRepository } from "./user.repository";
import { JwtPayload } from "./jwt-payload.interface";
import * as config from 'config';

const jwtConfig = config.get('jwt');

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {

    constructor(@InjectRepository(UserRepository) private userRepository: UserRepository) {
        super({
            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
            secretOrKey: process.env.JWT_SECRET || jwtConfig.secret
        })
    }

    async validate(payload: JwtPayload) {
        const {username} = payload;
        const user = await this.userRepository.findOne({username});

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

        return user;
    }

}

in tasks.controller i use it like this

@Controller('tasks')
@UseGuards(AuthGuard('jwt'))

my auth.module.ts

import { Module } from '@nestjs/common';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserRepository } from './user.repository';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { JwtStrategy } from './jwt.strategy';
import * as config from 'config';

const jwtConfig = config.get('jwt');

@Module({
    imports: [
        PassportModule.register({defaultStrategy: 'jwt'}),
        JwtModule.register({
            secret: process.env.JWT_SECRET || jwtConfig.secret,
            signOptions: {
                expiresIn: jwtConfig.expiresIn
            }
        }),
        TypeOrmModule.forFeature([UserRepository])
    ],
    controllers: [AuthController],
    providers: [
        AuthService,
        JwtStrategy
    ],
    exports: [
        JwtStrategy,
        PassportModule
    ]
})
export class AuthModule { }

I want to be able to log user out and the token should be invalid though and return 401

2

2 Answers

3
votes

Just logging out the user doesn't make a JWT token invalid (unless the token has expired).

In order to make sure that the token is not valid after logout, you need to apply some extra strategy. One common approach is to blacklist the token and maintain a list of blacklisted tokens.

For that to work, on logout, you can add blacklist the token and add it into the blacklisted-tokens list. And in authentication, you can add check if the token is blacklisted and throw error accordingly.

Check this answer for more ideas on dealing with this problem: https://stackoverflow.com/a/23089839/1906361

2
votes

What you're trying to do is very uncommon, just FYI.

Usually, you'd just delete the token in the user's LocalStorage.

You can jump through some hoops and blacklist the token but that's a lot of work for something that is not necessary in most cases. If you want extra security, choose a shorter expiry time for the token.