Skip to content

Commit

Permalink
Merge pull request #18 from one-piece-team1/develop
Browse files Browse the repository at this point in the history
Feat Secure
  • Loading branch information
libterty authored Mar 25, 2021
2 parents ac4451c + 3c64e8e commit a4283cc
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 37 deletions.
12 changes: 12 additions & 0 deletions config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ const packageDescriptionGetter = (): string => {
: 'service evaluate open api';
};

/**
* @description Cors white lists
* @private
* @param {string} env
* @returns {boolean | string[]}
*/
const corsWhiteLists = (env: string): boolean | string[] => {
if (env === 'production' || env === 'stage') return [process.env.WEBDOMAIN, process.env.IOSDOMAIN, process.env.ANDRIODDOMAIN];
return true;
}

// load config
dotenv.config();

Expand All @@ -59,6 +70,7 @@ const configs = {
HOST: process.env.APPHOST || 'localhost',
PORT: process.env.APPPORT || 8080,
WSPORT: process.env.WSPORT || 84,
CORSORIGIN: corsWhiteLists(env),

EVENT_STORE_SETTINGS: {
protocol: process.env.EVENTSTOREPROTOCOL || 'http',
Expand Down
55 changes: 55 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@
"fastify-cors": "^4.1.0",
"fastify-swagger": "^3.5.0",
"grpc": "^1.24.4",
"helmet": "^4.4.1",
"ioredis": "^4.19.2",
"lodash": "^4.17.20",
"morgan": "^1.10.0",
"node-rdkafka": "^2.10.1",
"pg": "^8.5.1",
"reflect-metadata": "^0.1.13",
Expand All @@ -73,9 +75,11 @@
"@nestjs/schematics": "^7.0.0",
"@nestjs/testing": "^7.0.0",
"@types/express": "^4.17.3",
"@types/helmet": "^4.0.0",
"@types/ioredis": "^4.17.7",
"@types/jest": "26.0.10",
"@types/lodash": "^4.14.165",
"@types/morgan": "^1.9.2",
"@types/node": "^13.9.1",
"@types/proxy-addr": "^2.0.0",
"@types/request-promise": "^4.1.46",
Expand Down
4 changes: 3 additions & 1 deletion src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { MiddlewareConsumer, Module, NestModule, RequestMethod } from '@nestjs/common';
import { GatewayModule } from './gateways/gateway.module';
import { RateMiddleware } from 'middlewares/rate-limit';
import { RateMiddleware } from './middlewares/rate-limit';
import { AuthMiddleware } from './middlewares/auth.service';
import { ChatSocketGateway } from './sockets/chat.gateway';
import { ChatSocketService } from './sockets/chat.service';
import { ChatConsumerService } from './consumers/chat.consumer';
Expand All @@ -13,5 +14,6 @@ import { ChatMessageRoutingService } from './handlers/chat.handler';
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(RateMiddleware).forRoutes({ path: '*', method: RequestMethod.ALL });
consumer.apply(AuthMiddleware).forRoutes({ path: '*', method: RequestMethod.ALL });
}
}
14 changes: 11 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import { Logger, ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { NestFastifyApplication } from '@nestjs/platform-fastify';
import { Transport } from '@nestjs/microservices';
import helmet from 'helmet';
import morgan from 'morgan';
import { AppModule } from './app.module';
import { config } from '../config';
import { Transport } from '@nestjs/microservices';

async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(AppModule);
app.connectMicroservice({
transport: Transport.TCP,
});

app.use(
morgan('combined', {
skip: (req, res) => res.statusCode < 400,
}),
);
app.useGlobalPipes(
new ValidationPipe({
skipMissingProperties: true,
Expand All @@ -21,9 +27,11 @@ async function bootstrap() {
app.setGlobalPrefix(`${config.PREFIX}${config.API_EXPLORER_PATH}`);
app.enableCors({
credentials: true,
origin: true,
origin: config.CORSORIGIN,
methods: ['GET', 'POST', 'PUT', 'DELETE'],
preflightContinue: true,
});
app.use(helmet());
app.startAllMicroservices();
await app.listen(config.PORT);
Logger.log(`Server start on ${config.HOST}:${config.PORT}`, 'Bootstrap', true);
Expand Down
58 changes: 25 additions & 33 deletions src/middlewares/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,66 +1,58 @@
import { HttpException, HttpStatus, Injectable, Logger, NestMiddleware, UnauthorizedException } from '@nestjs/common';
import { Injectable, Logger, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import { config } from '../../config';
import { APIRequestFactory } from '../libs/request-factory';

@Injectable()
export class AuthService implements NestMiddleware {
export class AuthMiddleware implements NestMiddleware {
private logger: Logger = new Logger('AuthService');

/**
* @description Auth validation Handler
* @public
* @param {Request} req
* @param {Response} res
* @param {NextFunction} next
* @returns {Promise<void | Response>}
* @returns {void | Response}
*/
public async use(req: Request, res: Response, next: NextFunction): Promise<void | Response> {
public use(req: Request, res: Response, next: NextFunction): void | Response {
if (!this.originHandling(req)) {
this.logger.error(`${req.ip} from ${req.hostname} send malware request with wrong origin`, '', 'UserOriginError');
return res.sendStatus(403);
}
// check if routes is exception or not
if (this.exceptRoutes(req.baseUrl)) return next();
// check token
if (!req.headers.authorization) return res.sendStatus(403);
try {
// get user data from user sercice
const response = await this.requestUesr(req.headers.authorization);
if (response.statusCode !== 200) return res.sendStatus(403);
next();
} catch (error) {
this.logger.log(error.message, 'Auth-Err');
return res.status(403).json({ status: 'error', message: error.message });
if (!req.headers.authorization) {
this.logger.error(`${req.ip} from ${req.hostname} send malware request with token`, '', 'TokenError');
return res.sendStatus(403);
}
next();
}

/**
* @description Handle Exception Routes which don't need to auth verify
* @private
* @param {string} routes
* @returns {boolean}
*/
protected exceptRoutes(routes: string): boolean {
private exceptRoutes(routes: string): boolean {
for (let i = 0; i < config.MS_EXCEPT.length; i++) {
if (routes.indexOf(config.MS_EXCEPT[i]) >= 0) return true;
}
return false;
}

/**
* @description Request user info by token to identify if it's validate user
* @param {string} token
* @returns {Promise<any>}
* @description Origin header handling due to Nestjs CORs has issued for handling
* @private
* @param {Request} req
* @returns {void}
*/
protected async requestUesr(token: string): Promise<any> {
try {
const service = config.MS_SETTINGS[0];
return await APIRequestFactory.createRequest('standard').makeRequest({
url: `http://${service.host}:${service.port}/users/info`,
method: 'GET',
headers: {
Authorization: token,
},
json: true,
});
} catch (error) {
this.logger.log(error.message, 'Auth-Request-Err');
throw new Error(error.message);
}
private originHandling(req: Request): boolean {
const whiteLists: boolean | string[] = config.CORSORIGIN;
if (typeof whiteLists === 'boolean') return true;
if (!req.headers.origin) return false;
if (whiteLists.indexOf(req.headers.origin) !== -1) return true;
return false;
}
}

0 comments on commit a4283cc

Please sign in to comment.