Skip to content

Commit 570c9da

Browse files
committed
feat(server): upgrade express-js example
1 parent c0857ce commit 570c9da

File tree

4 files changed

+58
-80
lines changed

4 files changed

+58
-80
lines changed

servers/node-express-js/app.js

Lines changed: 53 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ if (process.env.NODE_ENV !== 'production') {
1313

1414
const logger = require('./src/logger');
1515
logger.warn(`Starting with NODE_ENV=${config.NODE_ENV}`);
16-
logger.warn(`config.CI is ${config.CI} and isCI is ${config.isCI()}`);
1716

1817
const { findIndex } = require('lodash');
1918
const express = require('express');
@@ -30,25 +29,7 @@ const db = require('./src/db');
3029
// ----------------------------security packages-----------------------------
3130
// --------------------------------------------------------------------------
3231
// All security features are prefixed with `--SEC--`
33-
// --SEC-- - github hengkiardo/express-enforces-ssl
34-
// Enforces HTTPS connections on any incoming requests.
35-
// In case of a non-encrypted HTTP request, express-enforces-ssl automatically
36-
// redirects to an HTTPS address using a 301 permanent redirect.
37-
// const expressEnforcesSsl = require('express-enforces-ssl');
38-
// --SEC--- Brute Force Protection
39-
// Brute forcing is the systematically enumerating of all possible candidates a solution and checking
40-
// whether each candidate satisfies the problem's statement. In web applications a login endpoint
41-
// can be the perfect candidate for this.
42-
const RateLimit = require('express-rate-limit');
43-
const SlowDown = require('express-slow-down');
44-
// --SEC-- - github helmetjs/expect-ct [NOT helmet]
45-
// The Expect-CT HTTP header tells browsers to expect Certificate Transparency
46-
const expectCt = require('expect-ct');
47-
// --SEC-- - github analog-nico/hpp [NOT helmet]
48-
// [http params pollution] security package to prevent http params pollution
49-
const hpp = require('hpp');
50-
// --SEC-- - [CSRF] github.com/expressjs/csurf [NOT helmet]
51-
const csrf = require('csurf');
32+
5233
// --SEC-- - authentication with JWT
5334
const passport = require('passport');
5435
const passportJWT = require('passport-jwt');
@@ -95,6 +76,14 @@ passport.use(
9576
})
9677
);
9778

79+
// --SEC-- - github helmetjs/expect-ct [NOT helmet]
80+
// The Expect-CT HTTP header tells browsers to expect Certificate Transparency
81+
const expectCt = require('expect-ct');
82+
// --SEC-- - github analog-nico/hpp [NOT helmet]
83+
// [http params pollution] security package to prevent http params pollution
84+
const hpp = require('hpp');
85+
// --SEC-- - [CSRF] github.com/expressjs/csurf [NOT helmet]
86+
const csrf = require('csurf');
9887
// --SEC-- - github ericmdantas/express-content-length-validator [NOT helmet]
9988
// large payload attacks - Make sure this application is
10089
// not vulnerable to large payload attacks
@@ -117,19 +106,13 @@ const app = express();
117106
// }
118107

119108
// if (config.isProd()) {
120-
// logger.verbose('Initializing express-enforce-ssl');
109+
// logger.warn('Initializing express-enforce-ssl');
121110
// // --SEC-- - github hengkiardo/express-enforces-ssl
122111
// // enforces HTTPS connections on any incoming requests.
123112
// app.enable('trust proxy');
124113
// app.use(expressEnforcesSsl());
125114
// }
126115

127-
// --------------------------------------------------------------------------
128-
// --------------------------------------------------------------------------
129-
// --------------------------------------------------------------------------
130-
// --------------------------------------------------------------------------
131-
logger.warn('Initializing helmet');
132-
133116
// --SEC-- - add Feature-Policy header
134117
// taken from https://github.com/helmetjs/helmet/issues/173
135118
app.use(
@@ -228,7 +211,7 @@ app.use(
228211
// specifies valid sources for JavaScript. This includes not only URLs loaded directly into <script>
229212
scriptSrc: [`'self'`],
230213
// specifies valid sources for sources for stylesheets.
231-
styleSrc: [`'self'`, `'unsafe-inline'`]
214+
styleSrc: [`'self'`, `'unsafe-inline'`, `https://*.googleapis.com`]
232215
// instructs user agents to treat all of a site's insecure URLs (those served over HTTP) as though
233216
// they have been replaced with secure URLs (those served over HTTPS). This directive is intended
234217
// for web sites with large numbers of insecure legacy URLs that need to be rewritten.
@@ -286,13 +269,6 @@ app.use(
286269
// compress all reqs using gzip
287270
app.use(compression());
288271

289-
app.use('/', express.static(path.join(__dirname, config.FRONT_END_PATH, '/')));
290-
291-
logger.warn('Initializing hpp');
292-
// --SEC-- - http params pollution: activate http parameters pollution
293-
// use this ALWAYS AFTER app.use(bodyParser.urlencoded()) [NOT helmet]
294-
app.use(hpp());
295-
296272
logger.warn('Initializing passportjs');
297273
app.use(passport.initialize());
298274
passport.serializeUser(function(user, done) {
@@ -303,58 +279,65 @@ passport.deserializeUser(function(user, done) {
303279
});
304280

305281
// Initialize bodyParser BEFORE CSRF!!!!!
306-
logger.verbose('Initializing bodyParser');
307-
app.use(bodyParser.json());
282+
logger.warn('Initializing bodyParser');
308283
app.use(
309284
bodyParser.urlencoded({
310285
extended: false
311286
})
312287
);
313288
app.use(cookieParser(config.COOKIE_SECRET));
314289

315-
// CSRF must be added AFTER bodyParser and cookieParser, but BEFORE all APIS to protect
316-
// logger.verbose('Initializing CSRF protection');
317-
// app.use(
318-
// csrf({
319-
// cookie: {
320-
// // http://expressjs.com/en/4x/api.html#req.cookies
321-
// key: '_csrf',
322-
// path: '/',
323-
// httpOnly: true,
324-
// secure: false, // if you enable https you should set this to true
325-
// signed: false, // investigate if csurf support signed cookies (probably not)
326-
// sameSite: 'strict', // https://www.owaspsafar.org/index.php/SameSite
327-
// maxAge: config.SESSION_TIMEOUT_MS
328-
// }
329-
// })
330-
// );
331-
// app.use((req, res, next) => {
332-
// const csrfTokenToSendToFrontEnd = req.csrfToken();
333-
// res.cookie('XSRF-TOKEN', csrfTokenToSendToFrontEnd);
334-
// return next();
335-
// });
290+
// logger.warn('Initializing hpp (ALWAYS AFTER bodyParser)');
291+
// // --SEC-- - http params pollution: activate http parameters pollution
292+
// // use this ALWAYS AFTER app.use(bodyParser.urlencoded()) [NOT helmet]
293+
app.use(hpp());
336294

337-
logger.warn('Initializing REST apis');
295+
// CSRF must be added AFTER bodyParser and cookieParser, but BEFORE all APIS to protect
296+
logger.warn('Initializing CSRF protection');
297+
app.use(
298+
csrf({
299+
cookie: {
300+
// http://expressjs.com/en/4x/api.html#req.cookies
301+
key: '_csrf',
302+
path: '/',
303+
httpOnly: true,
304+
secure: false, // if you enable https you should set this to true
305+
signed: false, // investigate if csurf support signed cookies (probably not)
306+
sameSite: 'strict', // https://www.owaspsafar.org/index.php/SameSite
307+
maxAge: config.SESSION_TIMEOUT_MS
308+
}
309+
})
310+
);
311+
app.use((req, res, next) => {
312+
const csrfTokenToSendToFrontEnd = req.csrfToken();
313+
res.cookie('XSRF-TOKEN', csrfTokenToSendToFrontEnd);
314+
return next();
315+
});
338316

339317
// APIs for all route protected with CSRF
318+
logger.warn('Initializing REST apis');
340319
const APIS = require('./src/routes/apis');
341320
const routesApi = require('./src/routes/index')(express, passport);
342321
app.use(APIS.BASE_API_PATH, routesApi);
343322

344-
app.get('*', function(req, res) {
345-
res.sendFile(path.join(__dirname, config.FRONT_END_PATH, 'index.html'));
323+
app.all('/api/*', (req, res) => {
324+
logger.error('path API not exist');
325+
res.status(404).send();
346326
});
347327

328+
logger.warn('Initializing express static');
329+
app.use('/', express.static(path.join(__dirname, config.FRONT_END_PATH)));
330+
348331
// error handler
349-
// app.use((err, req, res, next) => {
350-
// if (err.code !== 'EBADCSRFTOKEN') {
351-
// return next(err);
352-
// }
353-
// // handle CSRF token errors here
354-
// res.status(403).json({
355-
// message: 'form tampered with'
356-
// });
357-
// });
332+
app.use((err, req, res, next) => {
333+
if (err.code !== 'EBADCSRFTOKEN') {
334+
return next(err);
335+
}
336+
// handle CSRF token errors here
337+
res.status(403).json({
338+
message: 'form tampered with'
339+
});
340+
});
358341

359342
// catch 404 and forward to error handler
360343
// taken from https://github.com/expressjs/express/blob/master/examples/error-pages/index.js

servers/node-express-js/src/config.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,12 @@
44
// don't use here logger.js because it requires config fully initialized
55

66
module.exports = {
7-
isCI: () => process.env.CI === 'yes' || process.env.CI === true,
87
isProd: () => process.env.NODE_ENV === 'production',
98
isTest: () => process.env.NODE_ENV === 'test',
109

11-
// used to run this server as back-end for integration testing on client-side
12-
// this method isn't used for integration testing on server-side
13-
isForE2eTest: () => process.env.NODE_ENV === 'e2e',
14-
15-
FRONT_END_PATH: process.env.FRONT_END_PATH || '../../dist/angular-cli-skeleton',
10+
FRONT_END_PATH: process.env.FRONT_END_PATH || '../../dist/client',
1611

1712
NODE_ENV: process.env.NODE_ENV || 'development',
18-
CI: process.env.CI || 'yes',
1913
PORT: process.env.PORT || process.env.NODE_ENV === 'production' ? 80 : 3000,
2014

2115
LOG_FOLDER: process.env.LOG_FOLDER || 'logs',

servers/node-express-js/src/logger.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ const logger = createLogger({
7373
handleExceptions: true
7474
})
7575
],
76-
level: !process.env.NODE_ENV ? 'error' : 'silly',
76+
level: !process.env.NODE_ENV ? 'silly' : 'error',
7777
exitOnError: false
7878
});
7979

80-
if (process.env.NODE_ENV !== 'production' && !config.isCI()) {
80+
if (process.env.NODE_ENV !== 'production') {
8181
logger.add(
8282
new transports.Console({
8383
handleExceptions: true,

servers/node-express-js/src/routes/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const RateLimit = require('express-rate-limit');
44
const SlowDown = require('express-slow-down');
55

6+
const bodyParser = require('body-parser');
67
const logger = require('../logger');
78
const config = require('../config');
89

@@ -44,7 +45,7 @@ module.exports = function(express, passport) {
4445
//----------------------------------------public-------------------------------------------
4546
//-----------------------------------------------------------------------------------------
4647
// auth login
47-
router.post(APIS.POST_LOGIN, [apiLimiter, apiSlowDown, ctrlAuth.login]);
48+
router.post(APIS.POST_LOGIN, [bodyParser.json(), apiLimiter, apiSlowDown, ctrlAuth.login]);
4849
// keep alive
4950
router.get(APIS.GET_KEEP_ALIVE, [apiLimiter, apiSlowDown, ctrlKeepAlive.keepAlive]);
5051
//-----------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)