Skip to content

Commit d3bd7ef

Browse files
committed
fix bug
1 parent 01f0ce3 commit d3bd7ef

File tree

8 files changed

+336
-322
lines changed

8 files changed

+336
-322
lines changed

package-lock.json

Lines changed: 219 additions & 224 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,14 @@
1010
"author": "",
1111
"license": "ISC",
1212
"dependencies": {
13-
"bcrypt": "^3.0.2",
13+
"bcrypt": "3.0.2",
1414
"body-parser": "1.17.2",
1515
"config": "2.0.1",
1616
"cors": "2.8.4",
17-
"crypto": "^1.0.1",
1817
"dotenv": "4.0.0",
1918
"express": "4.15.3",
20-
"jsonwebtoken": "^8.3.0",
21-
"pg": "^7.6.0",
19+
"jsonwebtoken": "8.3.0",
20+
"pg": "7.6.0",
2221
"reflect-metadata": "0.1.12",
2322
"sequelize": "4.41.0",
2423
"sequelize-typescript": "0.6.6",

src/Model/Person/Person.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {Table, Column, Model, CreatedAt, UpdatedAt, AllowNull, IsUUID, PrimaryKey, NotNull, BeforeCreate, BeforeUpdate, Length, DataType, AfterCreate, AfterUpdate, IsEmail, Unique} from 'sequelize-typescript';
22

3-
import {hashedPassword} from '../utils/password'
3+
import {hashedPassword} from '../../utils/password'
44

55
@Table({timestamps: true, tableName: "person", schema: "core"})
66
class Person extends Model<Person> {

src/Model/Token/Roles.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
//an enum
3+
interface Role {
4+
name: string,
5+
roles: string[]
6+
}
7+
8+
class Roles {
9+
static Admin:Role = {name: 'admin', roles: []}
10+
}
11+
12+
export default Roles
13+
export {
14+
Role, Roles
15+
}

src/Model/Token/Token.ts

Lines changed: 7 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,19 @@
11
const jwt = require('jsonwebtoken')
22
const config = require('config')
3-
const crypto = require('crypto')
4-
const algorithm = 'aes-256-ctr';
5-
const passwordForBody = config.token.passwordForBody
6-
const secret = config.token.secret
7-
const jwtMaxAge = config.token.maxAge
8-
const issuer = config.token.issuer
3+
import TokenUtil from './TokenUtil'
4+
import {Role, Roles} from './Roles'
95

10-
// C=create, R=read, U=update, D=delete
11-
enum action {
12-
None=null,
13-
14-
}
15-
16-
//an enum
17-
interface Role {
18-
name: string,
19-
roles: string[]
20-
}
21-
export class Roles {
22-
static Admin:Role = {name: 'admin', roles: []}
23-
}
24-
25-
export type Data = {
6+
type Data = {
267
permission: string,
278
role: Role
289
}
29-
export class TokenError {
30-
static None = null
31-
static EXPIRED = { status: 401, message: 'Token is expired' }
32-
33-
}
34-
35-
export class Token {
10+
class Token {
3611
data: Data // encrypted (type Data)
3712
expired: number
3813
}
3914

40-
export class TokenUtil {
41-
static sign(data:Data):Promise<string>{
42-
return new Promise((resolve, reject) => {
43-
const payload = encrypt(JSON.stringify(data), passwordForBody)
44-
jwt.sign(payload, secret, {issuer, expiresIn: jwtMaxAge}, (err, token) => {
45-
if(err) return reject(err)
46-
resolve(token)
47-
})
48-
})
49-
}
50-
static verify(token:string): Promise<Token>{
51-
return new Promise((resolve, reject) => {
52-
jwt.verify(token, secret, function(err, decoded) {
53-
if(err) return reject(err)
54-
const data = decrypt(decoded.data, passwordForBody)
55-
decoded.data = JSON.parse(data)
56-
return resolve(decoded)
57-
});
58-
})
59-
}
60-
static isValid(token:string): boolean|TokenError{
61-
TokenUtil.verify(token)
62-
.then(decoded => {
63-
if(decoded.expired > new Date().getTime()/1000){
64-
return TokenError.EXPIRED
65-
}
66-
if(decoded.data.permission !== ){
67-
return
68-
}
69-
})
70-
return true
71-
}
72-
}
73-
7415
export default Token
75-
76-
77-
// do not use a global iv for production,
78-
// generate a new one for each encryption
79-
80-
function encrypt(text:string, password:string): string{
81-
var cipher = crypto.createCipher(algorithm,password)
82-
var crypted = cipher.update(text,'utf8','hex')
83-
crypted += cipher.final('hex');
84-
return crypted;
85-
}
86-
87-
function decrypt(text:string, password:string): string{
88-
var decipher = crypto.createDecipher(algorithm,password)
89-
var dec = decipher.update(text,'hex','utf8')
90-
dec += decipher.final('utf8');
91-
return dec;
92-
}
93-
16+
export {
17+
TokenUtil, Data, Token
18+
}
9419

src/Model/Token/TokenUtil.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import * as crypto from 'crypto'
2+
import {Data, Token} from './Token'
3+
import TokenError from '../../enum/Error/TokenError'
4+
import config from 'config'
5+
import jwt from 'jsonwebtoken'
6+
import { Request, Response } from 'express';
7+
8+
const algorithm = 'aes-256-ctr';
9+
const passwordForBody = config.token.passwordForBody
10+
const secret = config.token.secret
11+
const jwtMaxAge = config.token.maxAge
12+
const issuer = config.token.issuer
13+
14+
export default class TokenUtil {
15+
static sign(data:Data):Promise<string>{
16+
return new Promise((resolve, reject) => {
17+
const payload = encrypt(JSON.stringify(data), passwordForBody)
18+
jwt.sign(payload, secret, {issuer, expiresIn: jwtMaxAge}, (err, token) => {
19+
if(err) return reject(err)
20+
resolve(token)
21+
})
22+
})
23+
}
24+
static verify(token:string): Promise<Token>{
25+
return new Promise((resolve, reject) => {
26+
jwt.verify(token, secret, function(err, decoded) {
27+
if(err) return reject(err)
28+
const data = decrypt(decoded.data, passwordForBody)
29+
decoded.data = JSON.parse(data)
30+
return resolve(decoded)
31+
});
32+
})
33+
}
34+
static validate(req:Request, res:Response): boolean|TokenError{
35+
if(!req.headers.authorization) {
36+
return TokenError.TOKEN_INVALID
37+
}
38+
const token:string = req.headers.authorization!
39+
TokenUtil.verify(token)
40+
.then(decoded => {
41+
if(decoded.expired > new Date().getTime()/1000){
42+
return TokenError.EXPIRED
43+
}
44+
45+
})
46+
return true
47+
}
48+
static authenticate(req:Request, res:Response):boolean|TokenError{
49+
if(!req.headers.authorization) {
50+
return TokenError.TOKEN_INVALID
51+
}
52+
return true
53+
}
54+
}
55+
56+
57+
// do not use a global iv for production,
58+
// generate a new one for each encryption
59+
60+
function encrypt(text:string, password:string): string{
61+
var cipher = crypto.createCipher(algorithm,password)
62+
var crypted = cipher.update(text,'utf8','hex')
63+
crypted += cipher.final('hex');
64+
return crypted;
65+
}
66+
67+
function decrypt(text:string, password:string): string{
68+
var decipher = crypto.createDecipher(algorithm,password)
69+
var dec = decipher.update(text,'hex','utf8')
70+
dec += decipher.final('utf8');
71+
return dec;
72+
}
73+
74+

src/app.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,31 @@ import * as express from 'express';
33
import * as bodyParser from 'body-parser';
44
import logger = require('./utils/logger');
55
import * as cors from "cors";
6+
import { Router, Request, Response } from 'express';
67

78
// DbUtils
89
import { Db_blog } from './utils/dbUtils'
10+
import TokenUtil from './Model/Token/TokenUtil'
911

1012
// model
11-
import Person from './model/Person'
12-
import { Validate } from 'sequelize-typescript';
13+
import Person from './model/Person/Person'
14+
1315

1416
//import controllers
1517
// import * as healthcheckController from './controllers/controller-healthcheck';
1618
// import * as sampleController from './controllers/controller-sample';
1719

1820
const app: express.Express = express();
19-
const router: express.Router = express.Router();
21+
const router: Router = express.Router();
2022
app.use(cors());
2123
app.use(bodyParser.json());
2224
app.use(router); // tell the app this is the router we are using
2325
//@ts-ignore
24-
app.use((req, res, next) => {
25-
if(!validateToken(req)){
26-
res.status(401).json({message: 'Token is not valid or expired'})
27-
}
28-
if(!authorizeToken(req)){
29-
res.status(403).json({message: 'User is not authorized'})
30-
}
31-
else
26+
app.use((req:Request, res:Response, next) => {
27+
// Intercept here
28+
TokenUtil.validate(req,res)
29+
TokenUtil.authenticate(req, res)
30+
next()
3231
})
3332

3433
//healthcheck routes

src/enum/Error/TokenError.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
export default class TokenError {
3+
static None = null
4+
static EXPIRED = { status: 401, message: 'Token is expired' }
5+
static UNAUTHORIZED = { status: 403, message: 'You are not allowed to access this page'}
6+
static TOKEN_INVALID = { status: 401, message: 'Token is invalid'}
7+
}

0 commit comments

Comments
 (0)