mirror of
https://github.com/wassname/talk.git
synced 2026-07-28 11:27:05 +08:00
Only on POST check for CSRF.
This commit is contained in:
@@ -7,6 +7,7 @@ const passport = require('./services/passport');
|
||||
const session = require('express-session');
|
||||
const RedisStore = require('connect-redis')(session);
|
||||
const redis = require('./services/redis');
|
||||
const csrf = require('csurf');
|
||||
|
||||
const app = express();
|
||||
|
||||
@@ -64,6 +65,17 @@ if (app.get('env') === 'production') {
|
||||
|
||||
app.use(session(session_opts));
|
||||
|
||||
//==============================================================================
|
||||
// CSRF MIDDLEWARE
|
||||
//==============================================================================
|
||||
|
||||
app.use(csrf());
|
||||
|
||||
app.use((err, req, res, next) => {
|
||||
res.locals._csrf = req.csrfToken();
|
||||
return next();
|
||||
});
|
||||
|
||||
//==============================================================================
|
||||
// PASSPORT MIDDLEWARE
|
||||
//==============================================================================
|
||||
|
||||
@@ -2,10 +2,10 @@ import React from 'react';
|
||||
|
||||
export const FormCSRFInput = React.createClass({
|
||||
render() {
|
||||
const token = ''; //$('meta[name="csrf-token"]').attr('content');
|
||||
const {csrfToken} = this.props;
|
||||
|
||||
return (
|
||||
<input type="hidden" name="authenticity_token" value={token} readOnly={true} />
|
||||
<input type="hidden" name="_csrf" value={csrfToken} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const csrf = require('csurf');
|
||||
|
||||
// Setup route middlewares for CSRF protection.
|
||||
// Default ignore methods are GET, HEAD, OPTIONS
|
||||
const csrfProtection = csrf({});
|
||||
|
||||
// Get /password-reset expects a signed token (JWT) in the hash.
|
||||
// Links to this endpoint are generated by /views/password-reset-email.ejs.
|
||||
router.get('/password-reset', csrfProtection, (req, res, next) => {
|
||||
router.get('/password-reset', (req, res, next) => {
|
||||
// TODO: store the redirect uri in the token or something fancy.
|
||||
// admins and regular users should probably be redirected to different places.
|
||||
res.render('password-reset', {redirectUri: process.env.TALK_ROOT_URL, csrfToken: req.csrfToken()});
|
||||
});
|
||||
|
||||
router.get('*', csrfProtection, (req, res) => {
|
||||
router.get('*', (req, res) => {
|
||||
res.render('admin', {basePath: '/client/coral-admin', csrfToken: req.csrfToken()});
|
||||
});
|
||||
|
||||
|
||||
@@ -4,6 +4,14 @@ const router = express.Router();
|
||||
const Asset = require('../../../models/asset');
|
||||
const scraper = require('../../../services/scraper');
|
||||
|
||||
const csrf = require('csurf');
|
||||
const bodyParser = require('body-parser');
|
||||
|
||||
// Setup route middlewares for CSRF protection.
|
||||
// Default ignore methods are GET, HEAD, OPTIONS
|
||||
const csrfProtection = csrf({});
|
||||
const parseForm = bodyParser.urlencoded({extended: false});
|
||||
|
||||
// List assets.
|
||||
router.get('/', (req, res, next) => {
|
||||
|
||||
@@ -59,7 +67,7 @@ router.get('/:asset_id', (req, res, next) => {
|
||||
});
|
||||
|
||||
// Adds the asset id to the queue to be scraped.
|
||||
router.post('/:asset_id/scrape', (req, res, next) => {
|
||||
router.post('/:asset_id/scrape', parseForm, csrfProtection, (req, res, next) => {
|
||||
|
||||
// Create a new asset scrape job.
|
||||
Asset
|
||||
|
||||
@@ -4,6 +4,14 @@ const authorization = require('../../../middleware/authorization');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
const csrf = require('csurf');
|
||||
const bodyParser = require('body-parser');
|
||||
|
||||
// Setup route middlewares for CSRF protection.
|
||||
// Default ignore methods are GET, HEAD, OPTIONS
|
||||
const csrfProtection = csrf({});
|
||||
const parseForm = bodyParser.urlencoded({extended: false});
|
||||
|
||||
/**
|
||||
* This returns the user if they are logged in.
|
||||
*/
|
||||
@@ -80,7 +88,7 @@ const HandleAuthPopupCallback = (req, res, next) => (err, user) => {
|
||||
/**
|
||||
* Local auth endpoint, will recieve a email and password
|
||||
*/
|
||||
router.post('/local', (req, res, next) => {
|
||||
router.post('/local', parseForm, csrfProtection, (req, res, next) => {
|
||||
|
||||
// Perform the local authentication.
|
||||
passport.authenticate('local', HandleAuthCallback(req, res, next))(req, res, next);
|
||||
|
||||
@@ -7,6 +7,14 @@ const wordlist = require('../../../services/wordlist');
|
||||
const authorization = require('../../../middleware/authorization');
|
||||
const _ = require('lodash');
|
||||
|
||||
const csrf = require('csurf');
|
||||
const bodyParser = require('body-parser');
|
||||
|
||||
// Setup route middlewares for CSRF protection.
|
||||
// Default ignore methods are GET, HEAD, OPTIONS
|
||||
const csrfProtection = csrf({});
|
||||
const parseForm = bodyParser.urlencoded({extended: false});
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.get('/', (req, res, next) => {
|
||||
@@ -82,7 +90,7 @@ router.get('/', (req, res, next) => {
|
||||
});
|
||||
});
|
||||
|
||||
router.post('/', wordlist.filter('body'), (req, res, next) => {
|
||||
router.post('/', parseForm, csrfProtection, wordlist.filter('body'), (req, res, next) => {
|
||||
|
||||
const {
|
||||
body,
|
||||
@@ -183,7 +191,7 @@ router.put('/:comment_id/status', authorization.needed('admin'), (req, res, next
|
||||
});
|
||||
});
|
||||
|
||||
router.post('/:comment_id/actions', (req, res, next) => {
|
||||
router.post('/:comment_id/actions', parseForm, csrfProtection, (req, res, next) => {
|
||||
|
||||
const {
|
||||
action_type,
|
||||
|
||||
@@ -9,6 +9,14 @@ const resetEmailFile = fs.readFileSync(path.resolve(__dirname, '../../../views/p
|
||||
const resetEmailTemplate = ejs.compile(resetEmailFile.toString());
|
||||
const authorization = require('../../../middleware/authorization');
|
||||
|
||||
const csrf = require('csurf');
|
||||
const bodyParser = require('body-parser');
|
||||
|
||||
// Setup route middlewares for CSRF protection.
|
||||
// Default ignore methods are GET, HEAD, OPTIONS
|
||||
const csrfProtection = csrf({});
|
||||
const parseForm = bodyParser.urlencoded({extended: false});
|
||||
|
||||
router.get('/', authorization.needed('admin'), (req, res, next) => {
|
||||
const {
|
||||
value = '',
|
||||
@@ -38,7 +46,7 @@ router.get('/', authorization.needed('admin'), (req, res, next) => {
|
||||
.catch(next);
|
||||
});
|
||||
|
||||
router.post('/:user_id/role', authorization.needed('admin'), (req, res, next) => {
|
||||
router.post('/:user_id/role', parseForm, csrfProtection, authorization.needed('admin'), (req, res, next) => {
|
||||
User
|
||||
.addRoleToUser(req.params.user_id, req.body.role)
|
||||
.then(() => {
|
||||
@@ -47,7 +55,7 @@ router.post('/:user_id/role', authorization.needed('admin'), (req, res, next) =>
|
||||
.catch(next);
|
||||
});
|
||||
|
||||
router.post('/:user_id/status', (req, res, next) => {
|
||||
router.post('/:user_id/status', parseForm, csrfProtection, (req, res, next) => {
|
||||
User
|
||||
.setStatus(req.params.user_id, req.body.status, req.body.comment_id)
|
||||
.then(status => {
|
||||
@@ -56,7 +64,7 @@ router.post('/:user_id/status', (req, res, next) => {
|
||||
.catch(next);
|
||||
});
|
||||
|
||||
router.post('/', (req, res, next) => {
|
||||
router.post('/', parseForm, csrfProtection, (req, res, next) => {
|
||||
const {email, password, displayName} = req.body;
|
||||
|
||||
User
|
||||
@@ -78,7 +86,7 @@ ErrPasswordTooShort.status = 400;
|
||||
* 1) the token that was in the url of the email link {String}
|
||||
* 2) the new password {String}
|
||||
*/
|
||||
router.post('/update-password', (req, res, next) => {
|
||||
router.post('/update-password', parseForm, csrfProtection, (req, res, next) => {
|
||||
const {token, password} = req.body;
|
||||
|
||||
if (!password || password.length < 8) {
|
||||
@@ -103,7 +111,7 @@ router.post('/update-password', (req, res, next) => {
|
||||
* this endpoint takes an email (username) and checks if it belongs to a User account
|
||||
* if it does, create a JWT and send an email
|
||||
*/
|
||||
router.post('/request-password-reset', (req, res, next) => {
|
||||
router.post('/request-password-reset', parseForm, csrfProtection, (req, res, next) => {
|
||||
const {email} = req.body;
|
||||
|
||||
if (!email) {
|
||||
@@ -158,7 +166,7 @@ router.put('/:user_id/bio', (req, res, next) => {
|
||||
});
|
||||
});
|
||||
|
||||
router.post('/:user_id/actions', authorization.needed(), (req, res, next) => {
|
||||
router.post('/:user_id/actions', parseForm, csrfProtection, authorization.needed(), (req, res, next) => {
|
||||
const {
|
||||
action_type,
|
||||
field,
|
||||
|
||||
@@ -2,6 +2,8 @@ const app = require('../../../../app');
|
||||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
|
||||
const csrf = require('csurf');
|
||||
|
||||
chai.use(require('chai-http'));
|
||||
|
||||
const User = require('../../../../models/user');
|
||||
@@ -29,6 +31,7 @@ describe('/api/v1/auth/local', () => {
|
||||
it('should send back the user on a successful login', () => {
|
||||
return chai.request(app)
|
||||
.post('/api/v1/auth/local')
|
||||
.field('_csrf', req.csrfToken())
|
||||
.send({email: 'maria@gmail.com', password: 'password!'})
|
||||
.catch((res) => {
|
||||
expect(res).to.have.status(200);
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
<body>
|
||||
<div id="root">
|
||||
<form id="reset-password-form">
|
||||
<input type="hidden" name="_csrf" value={{csrfToken}}/>
|
||||
<legend class="legend">Set new password</legend>
|
||||
<label for="password">
|
||||
New password
|
||||
|
||||
Reference in New Issue
Block a user