-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.js
158 lines (142 loc) · 4.12 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/**
* Created by zhangheng on 2017/8/21.
*/
const express = require('express')
const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser')
const jwt = require('jsonwebtoken')
const crypto = require('crypto')
const next = require('next')
const sass = require('node-sass')
const dev = process.env.NODE_ENV !== 'production'
const app = next({dev})
const handle = app.getRequestHandler()
const certKey = 'authSecret'
app.prepare()
.then(() => {
const server = express()
// Request body parsing middleware should be above methodOverride
server.use(bodyParser.json());
server.use(bodyParser.urlencoded({extended: false}));
server.use(cookieParser())
server.get('/auth/csrf', (req, res) => {
return res.status(200).json(
{
success: true,
message: 'success got csrf',
csrfToken: res.locals._csrf
})
})
server.get('/auth/session', (req, res) => {
let session = {
clientMaxAge: 60000,
csrfToken: res.locals._csrf
}
// Add user object to session if logged in
if (req.user) {
session.user = req.user
}
return res.status(200).json({
success: true,
message: 'success got session',
session: session
})
})
// Verify username and password, if passed, we return jwt token for client
// We also include xsrfToken for client, which will be used to prevent CSRF attack
// and, you should use random complicated key (JWT Secret) to make brute forcing token very hard
server.post('/authenticate', (req, res) => {
const {email, password} = req.body
if (email === 'test@test.com' || password === '111111') {
let token = jwt.sign({
email: email,
name: 'test user',
xsrfToken: crypto.createHash('md5').update(email).digest('hex')
}, certKey, {
expiresIn: 60 * 60
});
res.status(200).json({
success: true,
message: 'Enjoy your token',
token: token,
user: {
email: email,
name: 'test user',
verify: true
}
})
} else {
res.status(400).json({
success: false,
message: 'Authentication failed'
})
}
})
server.post('/signOut', (req, res) => {
res.status(200).json({
success: true,
message: 'sign out successfully',
})
})
// Authenticate middleware
server.use(unless(['/index', '/about', '/contact', '/auth/login', '/auth/register', '/_next'], (req, res, next) => {
const token = req.cookies['x-access-token'];
if (token) {
jwt.verify(token, certKey, (err, decoded) => {
if (err) {
res.redirect('/auth/login');
} else {
// if everything is good, save to request for use in other routes
req.decoded = decoded;
next();
}
})
} else {
res.redirect('/auth/login');
}
}))
// Api example to prevent CRSF attack
server.post('/api/preventCRSF', (req, res, next) => {
if (req.decoded.xsrfToken === req.get('X-XSRF-TOKEN')) {
res.status(200).json({
success: true,
message: 'Yes, this api is protected by CRSF attack'
})
} else {
res.status(400).json({
success: false,
message: 'CRSF attack is useless'
})
}
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(3000, (err) => {
if (err) throw err
console.log('> Ready on http://localhost:3000')
})
})
.catch((ex) => {
console.error(ex.stack)
process.exit(1)
})
function unless(paths, middleware) {
return function (req, res, next) {
let isHave = false
paths.forEach((path) => {
if (req.path==='/' || path === req.path || req.path.includes(path)) {
isHave = true
return
}
})
if(/\.(?:css|jpg|png|jpeg|ico)$/i.test(req.path)){
isHave = true
}
if (isHave) {
return next()
} else {
return middleware(req, res, next)
}
}
}