added encoding for the user data as json with proper encoding/escaping

This commit is contained in:
Wyatt Johnson
2018-01-18 13:58:45 -07:00
parent c99411b8fd
commit 8f1d9f051e
6 changed files with 57 additions and 14 deletions
+1
View File
@@ -61,6 +61,7 @@ if (ENABLE_TRACING && APOLLO_ENGINE_KEY) {
// Trust the first proxy in front of us, this will enable us to trust the fact
// that SSL was terminated correctly.
app.set('trust proxy', 1);
app.set('json escape', true);
// Enable a suite of security good practices through helmet. We disable
// frameguard to allow crossdomain injection of the embed.
-4
View File
@@ -209,10 +209,6 @@ const UserSchema = new Schema(
delete ret.__v;
delete ret._id;
delete ret.password;
delete ret.status.username.history;
delete ret.status.banned.history;
delete ret.status.suspension.history;
delete ret.tokens;
},
},
}
+4
View File
@@ -0,0 +1,4 @@
document.addEventListener('DOMContentLoaded', function(event) {
localStorage.setItem('auth', document.getElementById('auth').innerText);
setTimeout(function() { window.close(); }, 50);
});
+23 -3
View File
@@ -12,6 +12,8 @@ const debug = require('debug')('talk:services:passport');
const bowser = require('bowser');
const ms = require('ms');
const _ = require('lodash');
const { attachStaticLocals } = require('../middleware/staticTemplate');
const { encodeJSONForHTML } = require('./response');
// Create a redis client to use for authentication.
const { createClientFactory } = require('./redis');
@@ -81,6 +83,11 @@ const HandleGenerateCredentials = (req, res, next) => (err, user) => {
SetTokenForSafari(req, res, token);
// Set the cache control headers.
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
res.header('Expires', '-1');
res.header('Pragma', 'no-cache');
// Send back the details!
res.json({ user, token });
};
@@ -89,15 +96,28 @@ const HandleGenerateCredentials = (req, res, next) => (err, user) => {
* Returns the response to the login attempt via a popup callback with some JS.
*/
const HandleAuthPopupCallback = (req, res, next) => (err, user) => {
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
res.header('Expires', '-1');
res.header('Pragma', 'no-cache');
// Ensure the only scripts that can run here are those on the Talk domain.
res.header('Content-Security-Policy', "default-src 'self';");
// Attach static locals to the response locals object.
attachStaticLocals(res.locals);
// Attach the encoder on the response locals object.
res.locals.encodeJSONForHTML = encodeJSONForHTML;
if (err) {
return res.render('auth-callback', {
auth: JSON.stringify({ err, data: null }),
auth: { err, data: null },
});
}
if (!user) {
return res.render('auth-callback', {
auth: JSON.stringify({ err: errors.ErrNotAuthorized, data: null }),
auth: { err: errors.ErrNotAuthorized, data: null },
});
}
@@ -108,7 +128,7 @@ const HandleAuthPopupCallback = (req, res, next) => (err, user) => {
// We logged in the user! Let's send back the user data.
res.render('auth-callback', {
auth: JSON.stringify({ err: null, data: { user, token } }),
auth: { err: null, data: { user, token } },
});
};
+27
View File
@@ -0,0 +1,27 @@
/**
* escapeHTMLEntities will escape HTML entities with their unicode counterparts.
*
* @param {String} string the string containing potentially unsafe characters
*/
const escapeHTMLEntities = string =>
string.replace(/[<>&]/g, function(c) {
switch (c.charCodeAt(0)) {
case 0x3c:
return '\\u003c';
case 0x3e:
return '\\u003e';
case 0x26:
return '\\u0026';
default:
return c;
}
});
/**
* encodeJSONForHTML will encode an object to be loaded on an HTML page.
*
* @param {Object} obj javascript object to encode
*/
const encodeJSONForHTML = obj => escapeHTMLEntities(JSON.stringify(obj));
module.exports = { escapeHTMLEntities, encodeJSONForHTML };
+2 -7
View File
@@ -1,12 +1,7 @@
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
<%/* set the auth data in localStorage, this will ensure that only
javascript on the same domain can access the data, they can listen
for updates by attaching to localStorage event changes */%>
localStorage.setItem('auth', '<%- auth %>');
setTimeout(function() { window.close(); }, 50);
</script>
<script type="application/json" id="auth"><%- encodeJSONForHTML(auth) %></script>
<script type="text/javascript" src="<%= STATIC_URL %>public/javascripts/auth-callback.js"></script>
</body>
</html>