diff --git a/bin/cli-users b/bin/cli-users index 64d51e3b4..6e901f529 100755 --- a/bin/cli-users +++ b/bin/cli-users @@ -161,7 +161,10 @@ async function searchUsers() { } return data.users.nodes.map(user => { - const emails = user.emails.join(', '); + const emails = user.profiles + .filter(({ provider }) => provider === 'local') + .map(({ id }) => id) + .join(', '); return { name: `${user.username} (${emails}) ${user.id.gray} - ${ user.role.gray diff --git a/models/user.js b/models/user.js index 2aae9c4d3..717e43a88 100644 --- a/models/user.js +++ b/models/user.js @@ -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; }, }, } diff --git a/package.json b/package.json index 92dcd7f51..90abdf2e7 100644 --- a/package.json +++ b/package.json @@ -92,6 +92,7 @@ "dotenv": "^4.0.0", "ejs": "^2.5.7", "env-rewrite": "^1.0.2", + "escape-html": "^1.0.3", "eventemitter2": "^4.1.2", "exports-loader": "^0.6.4", "express": "4.16.0", diff --git a/public/javascripts/auth-callback.js b/public/javascripts/auth-callback.js new file mode 100644 index 000000000..f91f4d743 --- /dev/null +++ b/public/javascripts/auth-callback.js @@ -0,0 +1,4 @@ +document.addEventListener('DOMContentLoaded', function(event) { + localStorage.setItem('auth', document.getElementById('auth').innerText); + setTimeout(function() { window.close(); }, 50); +}); \ No newline at end of file diff --git a/services/passport.js b/services/passport.js index 369dc5e5c..59215dd54 100644 --- a/services/passport.js +++ b/services/passport.js @@ -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 } }, }); }; diff --git a/services/response.js b/services/response.js new file mode 100644 index 000000000..bfd3a7c97 --- /dev/null +++ b/services/response.js @@ -0,0 +1,10 @@ +const escapeHTMLEntities = require('escape-html'); + +/** + * 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 }; diff --git a/views/auth-callback.ejs b/views/auth-callback.ejs index 22103226d..307e84928 100644 --- a/views/auth-callback.ejs +++ b/views/auth-callback.ejs @@ -1,12 +1,7 @@
- + + diff --git a/yarn.lock b/yarn.lock index 5df93e694..4d5d3f52d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2931,7 +2931,7 @@ es6-weak-map@^2.0.1: es6-iterator "^2.0.1" es6-symbol "^3.1.1" -escape-html@~1.0.3: +escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"