From b205ba6a0dcbf431363e7e08ee1bf118fca38e6a Mon Sep 17 00:00:00 2001 From: Clement Michaud Date: Sat, 28 Jan 2017 02:33:45 +0100 Subject: [PATCH] Use a rendered html email template for identity check --- src/lib/identity_check.js | 38 ++-- src/lib/routes/reset_password.js | 1 + src/lib/routes/u2f_register_handler.js | 1 + src/public_html/js/login.js | 2 +- src/resources/email-template.ejs | 254 +++++++++++++++++++++++++ test/unitary/test_identity_check.js | 1 - 6 files changed, 281 insertions(+), 16 deletions(-) create mode 100644 src/resources/email-template.ejs diff --git a/src/lib/identity_check.js b/src/lib/identity_check.js index 96d1f9d8..bd1550d2 100644 --- a/src/lib/identity_check.js +++ b/src/lib/identity_check.js @@ -4,9 +4,13 @@ var randomstring = require('randomstring'); var Promise = require('bluebird'); var util = require('util'); var exceptions = require('./exceptions'); +var fs = require('fs'); +var ejs = require('ejs'); module.exports = identity_check; +var filePath = __dirname + '/../resources/email-template.ejs'; +var email_template = fs.readFileSync(filePath, 'utf8'); // IdentityCheck class @@ -24,15 +28,8 @@ IdentityCheck.prototype.issue_token = function(userid, email, content, logger) { this._logger.debug('identity_check: issue identity token %s for 5 minutes', token); return this._user_data_store.issue_identity_check_token(userid, token, content, five_minutes) .then(function() { - that._logger.debug('identity_check: send email to %s', email); - return that._send_identity_check_email(email, token); - }) -} - -IdentityCheck.prototype._send_identity_check_email = function(email, token) { - var url = util.format('%s?identity_token=%s', email.hook_url, token); - var email_content = util.format('Register', url); - return this._email_sender.send(email.to, email.subject, email_content); + return Promise.resolve(token); + }); } IdentityCheck.prototype.consume_token = function(token, logger) { @@ -107,14 +104,27 @@ function identity_check_post(endpoint, icheck_interface) { throw new exceptions.IdentityError('Missing user id or email address'); } - var email = {}; - email.to = email_address; - email.subject = 'Identity Verification'; - email.hook_url = util.format('https://%s%s', req.headers.host, req.headers['x-original-uri']); - return identity_check.issue_token(userid, email, undefined, logger); + return identity_check.issue_token(userid, undefined, logger); }, function(err) { throw new exceptions.AccessDeniedError(); }) + .then(function(token) { + var original_url = util.format('https://%s%s', req.headers.host, req.headers['x-original-uri']); + var link_url = util.format('%s?identity_token=%s', original_url, token); + var email = {}; + + var d = {}; + d.url = link_url; + d.button_title = 'Continue'; + d.title = icheck_interface.email_subject; + + email.to = email_address; + email.subject = icheck_interface.email_subject; + email.content = ejs.render(email_template, d); + + logger.info('POST identity_check: send email to %s', email.to); + return email_sender.send(email.to, email.subject, email.content); + }) .then(function() { res.status(204); res.send(); diff --git a/src/lib/routes/reset_password.js b/src/lib/routes/reset_password.js index 49b32e47..006dfa1f 100644 --- a/src/lib/routes/reset_password.js +++ b/src/lib/routes/reset_password.js @@ -9,6 +9,7 @@ var icheck_interface = { challenge: CHALLENGE, render_template: 'reset-password', pre_check_callback: pre_check, + email_subject: 'Reset your password', } module.exports = { diff --git a/src/lib/routes/u2f_register_handler.js b/src/lib/routes/u2f_register_handler.js index 0ecac0e3..2c2600a3 100644 --- a/src/lib/routes/u2f_register_handler.js +++ b/src/lib/routes/u2f_register_handler.js @@ -8,6 +8,7 @@ var icheck_interface = { challenge: CHALLENGE, render_template: 'u2f-register', pre_check_callback: pre_check, + email_subject: 'Register your U2F device', } module.exports = { diff --git a/src/public_html/js/login.js b/src/public_html/js/login.js index d73ba0f0..38114d62 100644 --- a/src/public_html/js/login.js +++ b/src/public_html/js/login.js @@ -23,7 +23,7 @@ function onLoginButtonClicked() { validateFirstFactor(username, password, function(err) { if(err) { - onFirstFactorFailure(err); + onFirstFactorFailure(err.responseText); return; } onFirstFactorSuccess(); diff --git a/src/resources/email-template.ejs b/src/resources/email-template.ejs new file mode 100644 index 00000000..f29d5afc --- /dev/null +++ b/src/resources/email-template.ejs @@ -0,0 +1,254 @@ + + + + + + Simples-Minimalistic Responsive Template + + + + + + + + + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + +
 
+ + + + + + + +
+

<%= title %>

+
+ +
 
+
+
+ + + + + + + + +
+ + + + + + +
 
+
+ + + + + + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + +
 
+ + + + + + + + + + + + + + + + + + +
+ This email has been sent to you in order to validate your identity. Please ignore it if you do not know why you received it. +
 
+ <%= button_title %> +
+
 
+
+
+ + + + + + + + +
+ + + + + + + + + + + + +
 
 
 
+
+ + + + + + + + +
+ + + + + + +
+ + + + + + + + + + + +
+ Please ignore this email if you did not initiate the process. +
+
+
+ + + + + diff --git a/test/unitary/test_identity_check.js b/test/unitary/test_identity_check.js index 555cb197..7100db1e 100644 --- a/test/unitary/test_identity_check.js +++ b/test/unitary/test_identity_check.js @@ -130,7 +130,6 @@ describe('test identity check process', function() { assert(user_data_store.issue_identity_check_token.calledOnce); assert.equal(user_data_store.issue_identity_check_token.getCall(0).args[0], 'user'); assert.equal(user_data_store.issue_identity_check_token.getCall(0).args[3], 240000); - assert(email_sender.send.getCall(0).args[2].startsWith('