Add CSRF protection.

This commit is contained in:
Jonathan Cremin 2015-08-22 23:07:34 +01:00
parent 8e47c74b68
commit 0910b16e1e
5 changed files with 68 additions and 7 deletions

View file

@ -17,7 +17,7 @@ import debugname from 'debug';
const debug = debugname('hostr-web');
const router = new Router();
router.use(errors({template: path.join(__dirname, 'public', '404.html')}));
router.use(errors({template: path.join(__dirname, 'public', 'error.html')}));
let statsdOpts = {prefix: 'hostr-web', host: process.env.STATSD_HOST || 'localhost'};
router.use(stats(statsdOpts));
@ -39,6 +39,8 @@ router.use(function* (next) {
yield next;
});
router.use(csrf());
router.use(views('views', {
default: 'ejs'
}));

View file

@ -21,7 +21,7 @@
</div>
<div class='row vertical-center'>
<div class='col-md-12'>
<h2><%=err.status%></h2>
<h2>500</h2>
<h1>Sorry, It looks like you've hit an unexpected error.</h1>
<p class="lead">Refreshing might fix the problem. If not, sit tight! We're on it!</p>
</div>

47
web/public/error.html Normal file
View file

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html style='height:100%;'>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title ng-bind="Hostr">Hostr - File not found</title>
<link rel="icon" type="image/png" href="/images/favicon.png">
<link href='//fonts.googleapis.com/css?family=Lato:300,400' rel='stylesheet' type='text/css'>
<link href='//fonts.googleapis.com/css?family=Open+Sans:400,300,600' rel='stylesheet' type='text/css'>
<link href="/styles/app.css" rel="stylesheet" />
</head>
<body class='error'>
<div class='container main'>
<div class='row'>
<div class='col-md-12'>
<div class='error-logo'>
<a href='/'><img src='/images/logo-dark-r.png' width='26' height='22' /></a>
</div>
</div>
</div>
<div class='row vertical-center'>
<div class='col-md-12'>
<h2>{{ status }}</h2>
{% if status >= 500 %}
<h1>{{ error }}</h1>
<p>Refreshing might fix the problem. If not, sit tight! We're on it!</p>
{% elseif status === 404 %}
<h1>Sorry, it looks like the file you asked for is gone.</h1>
<a href='/'>Take Me Home</a>
{% else %}
<h1>{{ error }}</h1>
<a href='/'>Take Me Home</a>
{% endif %}
</p>
</div>
</div>
</div>
<script>
var _gaq=[['_setAccount','UA-66209-2'],['_setDomainName', 'hostr.co'],['_trackPageview']];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src='//www.google-analytics.com/ga.js';
s.parentNode.insertBefore(g,s)}(document,'script'));
</script>
</body>
</html>

View file

@ -65,6 +65,7 @@ export function* create() {
}
export function* cancel() {
this.assertCSRF();
const Users = this.db.Users;
const user = yield Users.findOne({_id: this.session.user.id});

View file

@ -4,8 +4,9 @@ export function* signin() {
if (!this.request.body.email) {
return yield this.render('signin', {csrf: this.csrf});
}
this.statsd.incr('auth.attempt', 1);
this.statsd.incr('auth.attempt', 1);
this.assertCSRF(this.request.body);
const user = yield authenticate.call(this, this.request.body.email, this.request.body.password);
if(!user) {
this.statsd.incr('auth.failure', 1);
@ -25,6 +26,7 @@ export function* signup() {
return yield this.render('signup', {csrf: this.csrf});
}
this.assertCSRF(this.request.body);
if (this.request.body.email !== this.request.body.confirm_email) {
return yield this.render('signup', {error: 'Emails do not match.', csrf: this.csrf});
} else if (this.request.body.email && !this.request.body.terms) {
@ -41,13 +43,19 @@ export function* signup() {
return yield this.render('signup', {error: e.message, csrf: this.csrf});
}
this.statsd.incr('auth.signup', 1);
return yield this.render('signup', {message: 'Thanks for signing up, we\'ve sent you an email to activate your account.'});
return yield this.render('signup', {message: 'Thanks for signing up, we\'ve sent you an email to activate your account.', csrf: ''});
}
export function* forgot(token) {
export function* forgot() {
const Reset = this.db.Reset;
const Users = this.db.Users;
if (this.request.body) {
return yield this.render('forgot', {token: null, csrf: this.csrf});
}
const token = this.params.token;
this.assertCSRF(this.request.body);
if (this.request.body.email) {
var email = this.request.body.email;
yield sendResetToken.call(this, email);
@ -87,9 +95,12 @@ export function* logout() {
}
export function* activate(code) {
export function* activate() {
const code = this.params.code;
if (yield activateUser.call(this, code)) {
this.statsd.incr('auth.activation', 1);
this.redirect('/');
} else {
this.throw(400);
}
this.redirect('/');
}