I am building a microservice project, with two of the services are:
- API Gateway: for routing to suitable service.
- Authentication service: for authenticating user credentials/user's tokens.
The Authentication service is built by NestJS with TCP protocol.
Forcase login:
- HTTP request from client to API Gateway. API Gateway send to Authentication service
const oAuthenticatedUser: LoginUserResponseDto = await this.authMicroServiceClient.send('login', loginRequest).toPromise()
for validating the email and password. It will return UserInfo (name, access_token and regresh_token) if user's credentials are correct.
For case: create-post
- HTTP request from client to API Gateway with access_token in
header
. Before calling to post-service for executing post-creation, API Gateway call Authentication service for verifying the token byconst authenReponse = await this.authMicroServiceClient.send('verify_access_token', { token: access_token }).toPromise();
My pain point: I cannot use Passport strategy in Authentication service for implementing common verifying token. Because the request to Authentication Service is now not a normal HTTP request. Then these current code are not able to use:
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { TJwtPayload } from '../../types/auth/jwt-payload.type';
import { UserSimpleDTO } from '@modules/user/dto';
import { ConfigService } from '@nestjs/config'
import { TokenService } from '@app/shared/services'
/**
* Powered Thuan
* @author thuan.nguyen
* @namespace auth
* @classname JwtAccessTokenStrategy
**/
@Injectable()
export class JwtAccessTokenStrategy extends PassportStrategy(Strategy, 'jwt-access-token') {
constructor(private readonly tokenService: TokenService, configService: ConfigService) {
super({
jwtFromRequest: ExtractJwt.fromExtractors([
ExtractJwt.fromAuthHeaderAsBearerToken(),
]),
ignoreExpiration: true,
secretOrKey: configService.get("JWT_ACCESS_SECRET"),
});
}
async validate(payload: TJwtPayload): Promise<UserSimpleDTO> {
const user = await this.tokenService.validatePayload(payload);
if (!user) {
throw new UnauthorizedException('Cannot find user via payload');
}
return user;
}
}
And
import { Strategy } from 'passport-local';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { UserService } from '../user/user.service';
import { UserLoginReqDTO } from '@modules/user/dto';
/**
* Powered by Thuan
* @author thuan.nguyen
* @namespace auth
* @classname LocalStrategy
**/
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor(
private userService: UserService,
) {
super({ usernameField: 'email' });
}
async validate(email: string, password: string): Promise<UserLoginReqDTO> {
const user: UserLoginReqDTO = await this.userService.getUserIfPasswordMatches(email, password);
if (!user) {
throw new UnauthorizedException();
}
return user;
}
}
My question is: My design is a good one or not. I would like to know the better design. And How to use above code with requests transfered by TCP protocol.
Thank you!