Use a rendered html email template for identity check
parent
cb98f0454a
commit
b205ba6a0d
|
@ -4,9 +4,13 @@ var randomstring = require('randomstring');
|
||||||
var Promise = require('bluebird');
|
var Promise = require('bluebird');
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
var exceptions = require('./exceptions');
|
var exceptions = require('./exceptions');
|
||||||
|
var fs = require('fs');
|
||||||
|
var ejs = require('ejs');
|
||||||
|
|
||||||
module.exports = identity_check;
|
module.exports = identity_check;
|
||||||
|
|
||||||
|
var filePath = __dirname + '/../resources/email-template.ejs';
|
||||||
|
var email_template = fs.readFileSync(filePath, 'utf8');
|
||||||
|
|
||||||
// IdentityCheck class
|
// 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);
|
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)
|
return this._user_data_store.issue_identity_check_token(userid, token, content, five_minutes)
|
||||||
.then(function() {
|
.then(function() {
|
||||||
that._logger.debug('identity_check: send email to %s', email);
|
return Promise.resolve(token);
|
||||||
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('<a href="%s">Register</a>', url);
|
|
||||||
return this._email_sender.send(email.to, email.subject, email_content);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityCheck.prototype.consume_token = function(token, logger) {
|
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');
|
throw new exceptions.IdentityError('Missing user id or email address');
|
||||||
}
|
}
|
||||||
|
|
||||||
var email = {};
|
return identity_check.issue_token(userid, undefined, logger);
|
||||||
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);
|
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
throw new exceptions.AccessDeniedError();
|
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() {
|
.then(function() {
|
||||||
res.status(204);
|
res.status(204);
|
||||||
res.send();
|
res.send();
|
||||||
|
|
|
@ -9,6 +9,7 @@ var icheck_interface = {
|
||||||
challenge: CHALLENGE,
|
challenge: CHALLENGE,
|
||||||
render_template: 'reset-password',
|
render_template: 'reset-password',
|
||||||
pre_check_callback: pre_check,
|
pre_check_callback: pre_check,
|
||||||
|
email_subject: 'Reset your password',
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
|
@ -8,6 +8,7 @@ var icheck_interface = {
|
||||||
challenge: CHALLENGE,
|
challenge: CHALLENGE,
|
||||||
render_template: 'u2f-register',
|
render_template: 'u2f-register',
|
||||||
pre_check_callback: pre_check,
|
pre_check_callback: pre_check,
|
||||||
|
email_subject: 'Register your U2F device',
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
|
@ -23,7 +23,7 @@ function onLoginButtonClicked() {
|
||||||
|
|
||||||
validateFirstFactor(username, password, function(err) {
|
validateFirstFactor(username, password, function(err) {
|
||||||
if(err) {
|
if(err) {
|
||||||
onFirstFactorFailure(err);
|
onFirstFactorFailure(err.responseText);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
onFirstFactorSuccess();
|
onFirstFactorSuccess();
|
||||||
|
|
|
@ -0,0 +1,254 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
|
<title>Simples-Minimalistic Responsive Template</title>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
/* Client-specific Styles */
|
||||||
|
#outlook a {padding:0;} /* Force Outlook to provide a "view in browser" menu link. */
|
||||||
|
body{width:100% !important; -webkit-text-size-adjust:100%; -ms-text-size-adjust:100%; margin:0; padding:0;}
|
||||||
|
/* Prevent Webkit and Windows Mobile platforms from changing default font sizes, while not breaking desktop design. */
|
||||||
|
.ExternalClass {width:100%;} /* Force Hotmail to display emails at full width */
|
||||||
|
.ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height: 100%;} /* Force Hotmail to display normal line spacing.*/
|
||||||
|
#backgroundTable {margin:0; padding:0; width:100% !important; line-height: 100% !important;}
|
||||||
|
img {outline:none; text-decoration:none;border:none; -ms-interpolation-mode: bicubic;}
|
||||||
|
a img {border:none;}
|
||||||
|
.image_fix {display:block;}
|
||||||
|
p {margin: 0px 0px !important;}
|
||||||
|
table td {border-collapse: collapse;}
|
||||||
|
table { border-collapse:collapse; mso-table-lspace:0pt; mso-table-rspace:0pt; }
|
||||||
|
a {color: #0a8cce;text-decoration: none;text-decoration:none!important;}
|
||||||
|
h1 { line-height: 30px; }
|
||||||
|
.button {padding: 15px 30px; border-radius: 10px; background: rgb(204, 204, 255); text-decoration:none; }
|
||||||
|
|
||||||
|
/*STYLES*/
|
||||||
|
table[class=full] { width: 100%; clear: both; }
|
||||||
|
/*IPAD STYLES*/
|
||||||
|
@media only screen and (max-width: 640px) {
|
||||||
|
a[href^="tel"], a[href^="sms"] {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #0a8cce; /* or whatever your want */
|
||||||
|
pointer-events: none;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
.mobile_link a[href^="tel"], .mobile_link a[href^="sms"] {
|
||||||
|
text-decoration: default;
|
||||||
|
color: #0a8cce !important;
|
||||||
|
pointer-events: auto;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
table[class=devicewidth] {width: 440px!important;text-align:center!important;}
|
||||||
|
table[class=devicewidthinner] {width: 420px!important;text-align:center!important;}
|
||||||
|
img[class=banner] {width: 440px!important;height:220px!important;}
|
||||||
|
img[class=colimg2] {width: 440px!important;height:220px!important;}
|
||||||
|
|
||||||
|
}
|
||||||
|
/*IPHONE STYLES*/
|
||||||
|
@media only screen and (max-width: 480px) {
|
||||||
|
a[href^="tel"], a[href^="sms"] {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #0a8cce; /* or whatever your want */
|
||||||
|
pointer-events: none;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
.mobile_link a[href^="tel"], .mobile_link a[href^="sms"] {
|
||||||
|
text-decoration: default;
|
||||||
|
color: #0a8cce !important;
|
||||||
|
pointer-events: auto;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
table[class=devicewidth] {width: 280px!important;text-align:center!important;}
|
||||||
|
table[class=devicewidthinner] {width: 260px!important;text-align:center!important;}
|
||||||
|
img[class=banner] {width: 280px!important;height:140px!important;}
|
||||||
|
img[class=colimg2] {width: 280px!important;height:140px!important;}
|
||||||
|
td[class=mobile-hide]{display:none!important;}
|
||||||
|
td[class="padding-bottom25"]{padding-bottom:25px!important;}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- Start of header -->
|
||||||
|
<table width="100%" bgcolor="#ffffff" cellpadding="0" cellspacing="0" border="0" id="backgroundTable" st-sortable="header">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table width="600" cellpadding="0" cellspacing="0" border="0" align="center" class="devicewidth">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td width="100%">
|
||||||
|
<table width="600" cellpadding="0" cellspacing="0" border="0" align="center" class="devicewidth">
|
||||||
|
<tbody>
|
||||||
|
<!-- Spacing -->
|
||||||
|
<tr>
|
||||||
|
<td height="20" style="font-size:1px; line-height:1px; mso-line-height-rule: exactly;"> </td>
|
||||||
|
</tr>
|
||||||
|
<!-- Spacing -->
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<!-- logo -->
|
||||||
|
<table width="140" align="center" border="0" cellpadding="0" cellspacing="0" class="devicewidth">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td width="300" height="50" align="center">
|
||||||
|
<h1><%= title %></h1>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<!-- end of logo -->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- Spacing -->
|
||||||
|
<tr>
|
||||||
|
<td height="20" style="font-size:1px; line-height:1px; mso-line-height-rule: exactly;"> </td>
|
||||||
|
</tr>
|
||||||
|
<!-- Spacing -->
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<!-- End of Header -->
|
||||||
|
<!-- Start of seperator -->
|
||||||
|
<table width="100%" bgcolor="#ffffff" cellpadding="0" cellspacing="0" border="0" id="backgroundTable" st-sortable="seperator">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table width="600" align="center" cellspacing="0" cellpadding="0" border="0" class="devicewidth">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td align="center" height="20" style="font-size:1px; line-height:1px;"> </td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<!-- End of seperator -->
|
||||||
|
<!-- Start Full Text -->
|
||||||
|
<table width="100%" bgcolor="#ffffff" cellpadding="0" cellspacing="0" border="0" id="backgroundTable" st-sortable="full-text">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table width="600" cellpadding="0" cellspacing="0" border="0" align="center" class="devicewidth">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td width="100%">
|
||||||
|
<table width="600" cellpadding="0" cellspacing="0" border="0" align="center" class="devicewidth">
|
||||||
|
<tbody>
|
||||||
|
<!-- Spacing -->
|
||||||
|
<tr>
|
||||||
|
<td height="20" style="font-size:1px; line-height:1px; mso-line-height-rule: exactly;"> </td>
|
||||||
|
</tr>
|
||||||
|
<!-- Spacing -->
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table width="560" align="center" cellpadding="0" cellspacing="0" border="0" class="devicewidthinner">
|
||||||
|
<tbody>
|
||||||
|
<!-- Title -->
|
||||||
|
<tr>
|
||||||
|
<td style="font-family: Helvetica, arial, sans-serif; font-size: 16px; color: #333333; text-align:center; line-height: 30px;" st-title="fulltext-content">
|
||||||
|
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.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- End of Title -->
|
||||||
|
<!-- spacing -->
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="20" style="font-size:1px; line-height:1px; mso-line-height-rule: exactly;"> </td>
|
||||||
|
</tr>
|
||||||
|
<!-- End of spacing -->
|
||||||
|
<!-- content -->
|
||||||
|
<tr>
|
||||||
|
<td style="font-family: Helvetica, arial, sans-serif; font-size: 16px; color: #666666; text-align:center; line-height: 30px;" st-content="fulltext-content">
|
||||||
|
<a href="<%= url %>" class="button"><%= button_title %></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- End of content -->
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- Spacing -->
|
||||||
|
<tr>
|
||||||
|
<td height="20" style="font-size:1px; line-height:1px; mso-line-height-rule: exactly;"> </td>
|
||||||
|
</tr>
|
||||||
|
<!-- Spacing -->
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<!-- end of full text -->
|
||||||
|
<!-- Start of seperator -->
|
||||||
|
<table width="100%" bgcolor="#ffffff" cellpadding="0" cellspacing="0" border="0" id="backgroundTable" st-sortable="seperator">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table width="600" align="center" cellspacing="0" cellpadding="0" border="0" class="devicewidth">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td align="center" height="30" style="font-size:1px; line-height:1px;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="550" align="center" height="1" bgcolor="#d1d1d1" style="font-size:1px; line-height:1px;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" height="30" style="font-size:1px; line-height:1px;"> </td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<!-- End of seperator -->
|
||||||
|
<!-- Start of Postfooter -->
|
||||||
|
<table width="100%" bgcolor="#ffffff" cellpadding="0" cellspacing="0" border="0" id="backgroundTable" st-sortable="postfooter" >
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table width="600" cellpadding="0" cellspacing="0" border="0" align="center" class="devicewidth">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td width="100%">
|
||||||
|
<table width="600" cellpadding="0" cellspacing="0" border="0" align="center" class="devicewidth">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="middle" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;color: #666666" st-content="postfooter">
|
||||||
|
Please ignore this email if you did not initiate the process.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- Spacing -->
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="20"></td>
|
||||||
|
</tr>
|
||||||
|
<!-- Spacing -->
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<!-- End of postfooter -->
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -130,7 +130,6 @@ describe('test identity check process', function() {
|
||||||
assert(user_data_store.issue_identity_check_token.calledOnce);
|
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[0], 'user');
|
||||||
assert.equal(user_data_store.issue_identity_check_token.getCall(0).args[3], 240000);
|
assert.equal(user_data_store.issue_identity_check_token.getCall(0).args[3], 240000);
|
||||||
assert(email_sender.send.getCall(0).args[2].startsWith('<a href="https://localhost/auth/test?identity_token='));
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
var handler = app.post.getCall(0).args[1];
|
var handler = app.post.getCall(0).args[1];
|
||||||
|
|
Loading…
Reference in New Issue