Skip to content

Commit cdecee3

Browse files
committed
🍪 CSRF Token and Input validation
1 parent 02b8a8b commit cdecee3

File tree

4 files changed

+120
-17
lines changed

4 files changed

+120
-17
lines changed

index.js

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,29 @@ const {
55
} = require("mustache");
66
const sitedata = require("./config.json");
77
const slugify = require("slugify");
8+
const csrf = require('csurf');
9+
const cookieParser = require('cookie-parser');
10+
const {
11+
check,
12+
validationResult
13+
} = require('express-validator');
814

915
const app = express();
1016
const port = 3005;
1117

12-
app.set('view engine', 'hbs');
13-
app.use(express.static('public'));
14-
app.set('views', './views');
15-
1618
app.use(express.json());
1719
app.use(express.urlencoded({
1820
extended: true
1921
}));
2022

23+
app.set('view engine', 'hbs');
24+
app.use(express.static('public'));
25+
app.set('views', './views');
26+
app.use(cookieParser());
27+
const csrfProtection = csrf({
28+
cookie: true
29+
});
30+
2131
app.listen(port, function() {
2232
console.log('listening on port ' + port);
2333
});
@@ -32,16 +42,34 @@ const day = getCurrentDate(date.getDate())
3242
const year = date.getFullYear()
3343
const formattedDate = year + "-" + month + "-" + day
3444

35-
app.get('/', function(req, res) {
45+
app.get('/', csrfProtection, function(req, res) {
46+
res.header('X-Frame-Options', 'DENY');
47+
res.header('X-XSS-Protection', '1; mode=block');
48+
res.header('X-Content-Type-Options', 'nosniff');
49+
res.header('Strict-Transport-Security', 'max-age=63072000');
3650
res.render('home', {
3751
post: {
3852
title: 'Create New Markdown Post',
39-
description: 'Create New Markdown Blog Post.'
53+
description: 'Create New Markdown Blog Post.',
54+
csrfToken: req.csrfToken()
4055
}
4156
});
4257
});
4358

44-
app.post('/', function(req, res) {
59+
app.post('/post', csrfProtection, [
60+
check('title', 'title length should be 50 to 60 characters Good for SEO')
61+
.isLength({
62+
min: 10,
63+
max: 65
64+
}),
65+
check('description', 'description length should be 100 to 140 characters Good for SEO')
66+
.isLength({
67+
min: 100,
68+
max: 155
69+
}),
70+
check('postcontent', 'Fill Some Post Content').not().isEmpty().trim().escape(),
71+
check('tag', 'Enter Atleast one Tag for Post').not().isEmpty().trim().escape(),
72+
], function(req, res) {
4573

4674
res.header('X-Frame-Options', 'DENY');
4775
res.header('X-XSS-Protection', '1; mode=block');
@@ -52,15 +80,12 @@ app.post('/', function(req, res) {
5280
const random_id = Math.floor(1000 + Math.random() * 9000)
5381
const basename = sitedata.url_data + "-" + random_id
5482

55-
if (blog_title == 0 || blog_title == "") {
56-
57-
res.status(200).json({
58-
sucess: 0,
59-
message: 'Error Something is Missing'
60-
});
83+
const errors = validationResult(req);
6184

85+
if (!errors.isEmpty()) {
86+
res.status(200).json(errors);
6287
} else {
63-
88+
6489
const seo_url = slugify(blog_title, {
6590
replacement: '-',
6691
remove: /[*+~.()'"!:@]/g,
@@ -100,4 +125,11 @@ app.use('/', function(req, res) {
100125
error: 1,
101126
message: 'Web App Error'
102127
});
103-
});
128+
});
129+
app.use(function(err, req, res, next) {
130+
if (err.code !== 'EBADCSRFTOKEN') return next(err)
131+
res.status(403).json({
132+
error: 1,
133+
message: 'Token Error'
134+
});
135+
})

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@
2525
},
2626
"homepage": "https://github.com/mskian/create-markdown-post#readme",
2727
"dependencies": {
28+
"cookie-parser": "^1.4.5",
29+
"csurf": "^1.11.0",
2830
"express": "^4.17.1",
31+
"express-validator": "^6.13.0",
2932
"hbs": "^4.1.2",
3033
"mustache": "^4.2.0",
3134
"slugify": "^1.6.2"

views/home.hbs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
<div class="container col-9" >
1919
<h2>{{post.title}}</h2>
20-
<form action="/" method="post" role="form" enctype="application/x-www-form-urlencoded">
20+
<form action="/post" method="post" role="form" enctype="application/x-www-form-urlencoded">
2121
<div class="form-group">
2222
<label for="Post title">Post title</label>
2323
<input type="text"class="form-input" name="title" id="title" placeholder="Title" required>
@@ -34,6 +34,7 @@
3434
<label for="Post title">Tag</label>
3535
<input type="text"class="form-input" name="tag" id="tag" placeholder="Post tag" required>
3636
</div>
37+
<input type="hidden" name="_csrf" value="{{ post.csrfToken }}">
3738
<button type="submit" class="btn btn-gotify btn-lg">Submit</button>
3839
</form>
3940
</div>

yarn.lock

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,14 @@ content-type@~1.0.4:
218218
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
219219
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
220220

221+
cookie-parser@^1.4.5:
222+
version "1.4.5"
223+
resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.5.tgz#3e572d4b7c0c80f9c61daf604e4336831b5d1d49"
224+
integrity sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==
225+
dependencies:
226+
cookie "0.4.0"
227+
cookie-signature "1.0.6"
228+
221229
cookie-signature@1.0.6:
222230
version "1.0.6"
223231
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
@@ -233,6 +241,25 @@ crypto-random-string@^2.0.0:
233241
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
234242
integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
235243

244+
csrf@3.1.0:
245+
version "3.1.0"
246+
resolved "https://registry.yarnpkg.com/csrf/-/csrf-3.1.0.tgz#ec75e9656d004d674b8ef5ba47b41fbfd6cb9c30"
247+
integrity sha512-uTqEnCvWRk042asU6JtapDTcJeeailFy4ydOQS28bj1hcLnYRiqi8SsD2jS412AY1I/4qdOwWZun774iqywf9w==
248+
dependencies:
249+
rndm "1.2.0"
250+
tsscmp "1.0.6"
251+
uid-safe "2.1.5"
252+
253+
csurf@^1.11.0:
254+
version "1.11.0"
255+
resolved "https://registry.yarnpkg.com/csurf/-/csurf-1.11.0.tgz#ab0c3c6634634192bd3d6f4b861be20800eeb61a"
256+
integrity sha512-UCtehyEExKTxgiu8UHdGvHj4tnpE/Qctue03Giq5gPgMQ9cg/ciod5blZQ5a4uCEenNQjxyGuzygLdKUmee/bQ==
257+
dependencies:
258+
cookie "0.4.0"
259+
cookie-signature "1.0.6"
260+
csrf "3.1.0"
261+
http-errors "~1.7.3"
262+
236263
debug@2.6.9:
237264
version "2.6.9"
238265
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -323,6 +350,14 @@ etag@~1.8.1:
323350
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
324351
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
325352

353+
express-validator@^6.13.0:
354+
version "6.13.0"
355+
resolved "https://registry.yarnpkg.com/express-validator/-/express-validator-6.13.0.tgz#270d9e8718386b04b1880b5bb7b2c1c2a91a412b"
356+
integrity sha512-gvLqMFPwEm+C1CQlF3l695ubY1Shd3AtfI5JDYXM0Ju0A2GsGX+VjjQN7TcHXF6cO8wPgU8hSSFqWecBR0Gx1g==
357+
dependencies:
358+
lodash "^4.17.21"
359+
validator "^13.6.0"
360+
326361
express@^4.17.1:
327362
version "4.17.1"
328363
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
@@ -500,7 +535,7 @@ http-errors@1.7.2:
500535
statuses ">= 1.5.0 < 2"
501536
toidentifier "1.0.0"
502537

503-
http-errors@~1.7.2:
538+
http-errors@~1.7.2, http-errors@~1.7.3:
504539
version "1.7.3"
505540
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
506541
integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==
@@ -646,6 +681,11 @@ latest-version@^5.1.0:
646681
dependencies:
647682
package-json "^6.3.0"
648683

684+
lodash@^4.17.21:
685+
version "4.17.21"
686+
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
687+
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
688+
649689
lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
650690
version "1.0.1"
651691
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
@@ -864,6 +904,11 @@ qs@6.7.0:
864904
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
865905
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
866906

907+
random-bytes@~1.0.0:
908+
version "1.0.0"
909+
resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b"
910+
integrity sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=
911+
867912
range-parser@~1.2.1:
868913
version "1.2.1"
869914
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
@@ -917,6 +962,11 @@ responselike@^1.0.2:
917962
dependencies:
918963
lowercase-keys "^1.0.0"
919964

965+
rndm@1.2.0:
966+
version "1.2.0"
967+
resolved "https://registry.yarnpkg.com/rndm/-/rndm-1.2.0.tgz#f33fe9cfb52bbfd520aa18323bc65db110a1b76c"
968+
integrity sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=
969+
920970
safe-buffer@5.1.2:
921971
version "5.1.2"
922972
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
@@ -1064,6 +1114,11 @@ touch@^3.1.0:
10641114
dependencies:
10651115
nopt "~1.0.10"
10661116

1117+
tsscmp@1.0.6:
1118+
version "1.0.6"
1119+
resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb"
1120+
integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==
1121+
10671122
type-fest@^0.20.2:
10681123
version "0.20.2"
10691124
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
@@ -1089,6 +1144,13 @@ uglify-js@^3.1.4:
10891144
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.14.3.tgz#c0f25dfea1e8e5323eccf59610be08b6043c15cf"
10901145
integrity sha512-mic3aOdiq01DuSVx0TseaEzMIVqebMZ0Z3vaeDhFEh9bsc24hV1TFvN74reA2vs08D0ZWfNjAcJ3UbVLaBss+g==
10911146

1147+
uid-safe@2.1.5:
1148+
version "2.1.5"
1149+
resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a"
1150+
integrity sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==
1151+
dependencies:
1152+
random-bytes "~1.0.0"
1153+
10921154
undefsafe@^2.0.5:
10931155
version "2.0.5"
10941156
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c"
@@ -1138,6 +1200,11 @@ utils-merge@1.0.1:
11381200
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
11391201
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
11401202

1203+
validator@^13.6.0:
1204+
version "13.7.0"
1205+
resolved "https://registry.yarnpkg.com/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857"
1206+
integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==
1207+
11411208
vary@~1.1.2:
11421209
version "1.1.2"
11431210
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"

0 commit comments

Comments
 (0)