Skip to content

How to create login and logout feature?  #269

@saadabdurrazaq

Description

@saadabdurrazaq

Middleware:
import jwt from 'jsonwebtoken';
import { ExpressMiddlewareInterface, Middleware } from 'routing-controllers';

import { Logger, LoggerInterface } from '../../decorators/Logger';

@Middleware({ type: 'before' })
export class JwtAuthMiddleware implements ExpressMiddlewareInterface {

constructor(
    @Logger(__filename) private log: LoggerInterface
) { }

public use(req: any, res: any, next: (err?: any) => any): void {
    const headers = req.headers as { authorization?: string } || req.headers['0'];
    const authHeader = headers.authorization;
    const authorization = req.header('authorization');

    console.log('authorization', authorization);
    // console.log('Headers:', req.headers);
    this.log.info('show token', headers);
    // console.log('res', res);
    if (!authHeader) {
        return res.status(401).send({ message: 'No token provided' });
    }

    const token = authHeader.split(' ')[1];
    if (!token) {
        return res.status(401).send({ message: 'Invalid token' });
    }

    jwt.verify(token, 'your-secret-key', (err, user) => {
        if (err) {
            return res.status(403).send({ message: 'Token is not valid' });
        }
        req.user = user;
        next();
    });
}

}

Controller:
import { IsNotEmpty } from 'class-validator';
import { Body, JsonController, Post, Req, Res } from 'routing-controllers';
import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi';

import { Logger, LoggerInterface } from '../../decorators/Logger';
import { AuthService } from '../services/AuthService';
// import { UserService } from '../services/UserService';
import { UserResponse } from './UserController';

class LoginBody {
@isnotempty()
public username: string;

@IsNotEmpty()
public password: string;

}

@jsoncontroller('/auth')
@openapi({ security: [{ basicAuth: [] }] })
export class AuthController {

constructor(
    // private userService: UserService,
    private authService: AuthService,
    @Logger(__filename) private log: LoggerInterface
) { }

@Post('/login')
@ResponseSchema(UserResponse)
public async login(@Body() body: LoginBody, @Res() res: any): Promise<any> {
    this.log.info(`Received login request with body: ${JSON.stringify(body)}`);

    const { user, token } = await this.authService.validateUser(body.username, body.password);

    if (!user) {
        return res.status(401).send({ message: 'Invalid username or password' });
    }

    res.status(200).send({
        status: 200,
        message: 'Login success',
        access_token: token,
        token_type: 'Bearer',
        user: {
            username: user.username,
        },
    });
}

@Post('/logout')
public async logout(@Req() req: any, @Res() res: any): Promise<void> {
    const token = req.headers.authorization.split(' ')[1];
    await this.authService.invalidateToken(token);
    res.status(200).send({ message: 'Logged out successfully' });
}

}

Service
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import { Service } from 'typedi';

import { Logger, LoggerInterface } from '../../decorators/Logger';
import { User } from '../models/User';
import { UserService } from './UserService';

@service()
export class AuthService {

constructor(
    private userService: UserService,
    @Logger(__filename) private log: LoggerInterface
) { }

public async validateUser(username: string, password: string): Promise<{ user: User | null, token?: string }> {
    this.log.info(`Validating user: ${username}, ${password}`);
    const user = await this.userService.findByUsername(username);
    if (user && await bcrypt.compare(password, user.password)) {
        const token = this.createToken(user);
        return { user, token };
    }
    return { user: undefined };
}

public createToken(user: User): string {
    return jwt.sign({ id: user.id, username: user.username }, 'your-secret-key', { expiresIn: '1h' });
}

public async invalidateToken(token: string): Promise<void> {
    // Implement token invalidation logic here (e.g., adding the token to a blacklist)
}

}

Repository
import knex, { Knex } from 'knex';
import { EntityRepository, Repository } from 'typeorm';

import knexConfig from '../../../src/knexfile';
import { User } from '../models/User';

const environment = process.env.NODE_ENV || 'development';
const DB: Knex = knex(knexConfig[environment]);
@entityrepository(User)
export class UserRepository extends Repository {
public async findOneByUsername(username: string): Promise<User | undefined> {
const user = await DB('user')
.where({ username })
.first();

    return user;
}

}

But I always failed

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions