mirror of https://github.com/calzoneman/sync.git
commit
62b81708ab
|
@ -12,6 +12,7 @@ var $util = require("../utilities");
|
|||
var Config = require("../config");
|
||||
var Server = require("../server");
|
||||
var session = require("../session");
|
||||
var csrf = require("./csrf");
|
||||
|
||||
/**
|
||||
* Handles a GET request for /account/edit
|
||||
|
@ -28,6 +29,8 @@ function handleAccountEditPage(req, res) {
|
|||
* Handles a POST request to edit a user"s account
|
||||
*/
|
||||
function handleAccountEdit(req, res) {
|
||||
csrf.verify(req);
|
||||
|
||||
var action = req.body.action;
|
||||
switch(action) {
|
||||
case "change_password":
|
||||
|
@ -204,6 +207,8 @@ function handleAccountChannelPage(req, res) {
|
|||
* Handles a POST request to modify a user"s channels
|
||||
*/
|
||||
function handleAccountChannel(req, res) {
|
||||
csrf.verify(req);
|
||||
|
||||
var action = req.body.action;
|
||||
switch(action) {
|
||||
case "new_channel":
|
||||
|
@ -394,6 +399,8 @@ function handleAccountProfilePage(req, res) {
|
|||
* Handles a POST request to edit a profile
|
||||
*/
|
||||
function handleAccountProfile(req, res) {
|
||||
csrf.verify(req);
|
||||
|
||||
if (!req.user) {
|
||||
return sendJade(res, "account-profile", {
|
||||
profileImage: "",
|
||||
|
@ -442,6 +449,8 @@ function handlePasswordResetPage(req, res) {
|
|||
* Handles a POST request to reset a user's password
|
||||
*/
|
||||
function handlePasswordReset(req, res) {
|
||||
csrf.verify(req);
|
||||
|
||||
var name = req.body.name,
|
||||
email = req.body.email;
|
||||
|
||||
|
|
|
@ -15,11 +15,14 @@ var db = require("../database");
|
|||
var Config = require("../config");
|
||||
var url = require("url");
|
||||
var session = require("../session");
|
||||
var csrf = require("./csrf");
|
||||
|
||||
/**
|
||||
* Processes a login request. Sets a cookie upon successful authentication
|
||||
*/
|
||||
function handleLogin(req, res) {
|
||||
csrf.verify(req);
|
||||
|
||||
var name = req.body.name;
|
||||
var password = req.body.password;
|
||||
var rememberMe = req.body.remember;
|
||||
|
@ -119,7 +122,10 @@ function handleLoginPage(req, res) {
|
|||
* Handles a request for /logout. Clears auth cookie
|
||||
*/
|
||||
function handleLogout(req, res) {
|
||||
csrf.verify(req);
|
||||
|
||||
res.clearCookie("auth");
|
||||
req.user = res.user = null;
|
||||
// Try to find an appropriate redirect
|
||||
var dest = req.query.dest || req.header("referer");
|
||||
dest = dest && dest.match(/login|logout|account/) ? null : dest;
|
||||
|
@ -159,6 +165,8 @@ function handleRegisterPage(req, res) {
|
|||
* Processes a registration request.
|
||||
*/
|
||||
function handleRegister(req, res) {
|
||||
csrf.verify(req);
|
||||
|
||||
var name = req.body.name;
|
||||
var password = req.body.password;
|
||||
var email = req.body.email;
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Adapted from https://github.com/expressjs/csurf
|
||||
*/
|
||||
|
||||
var csrf = require("csrf");
|
||||
var createError = require("http-errors");
|
||||
|
||||
var tokens = csrf();
|
||||
|
||||
exports.init = function csrfInit(req, res, next) {
|
||||
var secret = req.signedCookies._csrf;
|
||||
if (!secret) {
|
||||
secret = tokens.secretSync();
|
||||
res.cookie("_csrf", secret, { signed: true, httpOnly: true });
|
||||
}
|
||||
|
||||
var token;
|
||||
|
||||
req.csrfToken = function csrfToken() {
|
||||
if (token) {
|
||||
return token;
|
||||
}
|
||||
|
||||
token = tokens.create(secret);
|
||||
return token;
|
||||
};
|
||||
|
||||
next();
|
||||
};
|
||||
|
||||
exports.verify = function csrfVerify(req) {
|
||||
var secret = req.signedCookies._csrf;
|
||||
var token = req.body._csrf || req.query._csrf;
|
||||
|
||||
if (!tokens.verify(secret, token)) {
|
||||
throw createError(403, 'invalid csrf token', {
|
||||
code: 'EBADCSRFTOKEN'
|
||||
});
|
||||
}
|
||||
};
|
|
@ -14,7 +14,8 @@ function merge(locals, res) {
|
|||
siteDescription: Config.get("html-template.description"),
|
||||
siteAuthor: "Calvin 'calzoneman' 'cyzon' Montgomery",
|
||||
loginDomain: Config.get("https.enabled") ? Config.get("https.full-address")
|
||||
: Config.get("http.full-address")
|
||||
: Config.get("http.full-address"),
|
||||
csrfToken: res.req.csrfToken()
|
||||
};
|
||||
if (typeof locals !== "object") {
|
||||
return _locals;
|
||||
|
|
|
@ -14,6 +14,7 @@ var cookieParser = require("cookie-parser");
|
|||
var static = require("serve-static");
|
||||
var morgan = require("morgan");
|
||||
var session = require("../session");
|
||||
var csrf = require("./csrf");
|
||||
|
||||
const LOG_FORMAT = ':real-address - :remote-user [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"';
|
||||
morgan.token('real-address', function (req) { return req._ip; });
|
||||
|
@ -190,6 +191,7 @@ module.exports = {
|
|||
Logger.errlog.log("YOU SHOULD CHANGE THE VALUE OF cookie-secret IN config.yaml");
|
||||
}
|
||||
app.use(cookieParser(Config.get("http.cookie-secret")));
|
||||
app.use(csrf.init);
|
||||
app.use(morgan(LOG_FORMAT, {
|
||||
stream: require("fs").createWriteStream(path.join(__dirname, "..", "..",
|
||||
"http.log"), {
|
||||
|
@ -253,6 +255,10 @@ module.exports = {
|
|||
return res.status(413).end();
|
||||
} else if (err.message && err.message.match(/bad request/i)) {
|
||||
return res.status(400).end("Bad Request");
|
||||
} else if (err.message && err.message.match(/invalid csrf token/i)) {
|
||||
res.status(403);
|
||||
sendJade(res, 'csrferror', { path: req.path });
|
||||
return;
|
||||
}
|
||||
Logger.errlog.log(err.stack);
|
||||
res.status(500).end();
|
||||
|
|
|
@ -9,13 +9,15 @@
|
|||
"dependencies": {
|
||||
"bcrypt": "^0.8.1",
|
||||
"body-parser": "^1.10.2",
|
||||
"cheerio" : "^0.18.0",
|
||||
"cheerio": "^0.18.0",
|
||||
"compression": "^1.3.0",
|
||||
"cookie-parser": "^1.3.3",
|
||||
"csrf": "^2.0.6",
|
||||
"cytubefilters": "git://github.com/calzoneman/cytubefilters#33b7693c",
|
||||
"express": "^4.11.1",
|
||||
"express-minify": "^0.1.3",
|
||||
"graceful-fs": "^3.0.5",
|
||||
"http-errors": "^1.3.1",
|
||||
"jade": "^1.9.1",
|
||||
"json-typecheck": "^0.1.3",
|
||||
"morgan": "^1.5.1",
|
||||
|
|
|
@ -39,6 +39,7 @@ html(lang="en")
|
|||
tr
|
||||
th
|
||||
form.form-inline.pull-right(action="/account/channels", method="post", onsubmit="return confirm('Are you sure you want to delete #{c.name}? This cannot be undone');")
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
input(type="hidden", name="action", value="delete_channel")
|
||||
input(type="hidden", name="name", value="#{c.name}")
|
||||
button.btn.btn-xs.btn-danger(type="submit") Delete
|
||||
|
@ -51,6 +52,7 @@ html(lang="en")
|
|||
strong Channel Registration Failed
|
||||
p= newChannelError
|
||||
form(action="/account/channels", method="post")
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
input(type="hidden", name="action", value="new_channel")
|
||||
.form-group
|
||||
label.control-label(for="channelname") Channel Name
|
||||
|
|
|
@ -29,6 +29,7 @@ html(lang="en")
|
|||
p= errorMessage
|
||||
h3 Change Password
|
||||
form(action="/account/edit", method="post", onsubmit="return validatePasswordChange()")
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
input(type="hidden", name="action", value="change_password")
|
||||
.form-group
|
||||
label.control-label(for="username") Username
|
||||
|
@ -46,6 +47,7 @@ html(lang="en")
|
|||
hr
|
||||
h3 Change Email
|
||||
form(action="/account/edit", method="post", onsubmit="return submitEmail()")
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
input(type="hidden", name="action", value="change_email")
|
||||
.form-group
|
||||
label.control-label(for="username2") Username
|
||||
|
|
|
@ -25,6 +25,7 @@ html(lang="en")
|
|||
strong Error
|
||||
p= resetErr
|
||||
form(action="/account/passwordreset", method="post", role="form")
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
.form-group
|
||||
label.control-label(for="username") Username
|
||||
input#username.form-control(type="text", name="name")
|
||||
|
|
|
@ -32,6 +32,7 @@ html(lang="en")
|
|||
p= profileText
|
||||
h3 Edit Profile
|
||||
form(action="/account/profile", method="post", role="form")
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
.form-group
|
||||
label.control-label(for="profileimage") Image
|
||||
input#profileimage.form-control(type="text", name="image")
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
doctype html
|
||||
html(lang="en")
|
||||
head
|
||||
include head
|
||||
mixin head()
|
||||
body
|
||||
#wrap
|
||||
nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation")
|
||||
include nav
|
||||
mixin navheader()
|
||||
#nav-collapsible.collapse.navbar-collapse
|
||||
ul.nav.navbar-nav
|
||||
mixin navdefaultlinks(path)
|
||||
mixin navloginlogout(path)
|
||||
|
||||
section#mainpage.container
|
||||
.col-md-12
|
||||
.alert.alert-danger
|
||||
h1 Invalid Session
|
||||
p Your browser attempted to submit form data to <code>#{path}</code> with an invalid authentication token. This may be because:
|
||||
ul
|
||||
li Your session has expired
|
||||
li Your request was missing the authentication token
|
||||
li A malicious user has attempted to tamper with your session
|
||||
li Your browser does not support cookies, or they are not enabled
|
||||
| If the problem persists, please contact an administrator.
|
||||
a(href=path) Return to previous page
|
||||
|
||||
include footer
|
||||
mixin footer()
|
|
@ -26,6 +26,7 @@ html(lang="en")
|
|||
p= loginError
|
||||
h2 Login
|
||||
form(role="form", action="/login", method="post")
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
if redirect
|
||||
input(type="hidden", name="dest", value=redirect)
|
||||
.form-group
|
||||
|
|
|
@ -47,6 +47,7 @@ mixin navloginform(redirect)
|
|||
- loginDomain = ""
|
||||
.visible-lg
|
||||
form#loginform.navbar-form.navbar-right(action="#{loginDomain}/login", method="post")
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
input(type="hidden", name="dest", value=redirect)
|
||||
.form-group
|
||||
input#username.form-control(type="text", name="name", placeholder="Username")
|
||||
|
@ -60,7 +61,7 @@ mixin navloginform(redirect)
|
|||
button#login.btn.btn-default(type="submit") Login
|
||||
.visible-md
|
||||
p#loginform.navbar-text.pull-right
|
||||
a#login.navbar-link(href="#{loginDomain}/login?dest=#{redirect}") Log in
|
||||
a#login.navbar-link(href="#{loginDomain}/login?dest=#{encodeURIComponent(redirect)}") Log in
|
||||
span ·
|
||||
a#register.navbar-link(href="/register") Register
|
||||
|
||||
|
@ -69,4 +70,4 @@ mixin navlogoutform(redirect)
|
|||
p#logoutform.navbar-text.pull-right
|
||||
span#welcome Welcome, #{loginName}
|
||||
span ·
|
||||
a#logout.navbar-link(href="/logout?dest=#{redirect}") Logout
|
||||
a#logout.navbar-link(href="/logout?dest=#{encodeURIComponent(redirect)}&_csrf=#{csrfToken}") Logout
|
||||
|
|
|
@ -29,6 +29,7 @@ html(lang="en")
|
|||
p= registerError
|
||||
h2 Register
|
||||
form(role="form", action="/register", method="post", onsubmit="return verify()")
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
.form-group
|
||||
label.control-label(for="username") Username
|
||||
input#username.form-control(type="text", name="name")
|
||||
|
|
Loading…
Reference in New Issue