[interchange] Use bcrypt in Strap demo
Josh Lavin
interchange-cvs at icdevgroup.org
Tue Nov 17 18:51:15 UTC 2015
commit f1de50ef12da5752046b8c59dacdbd0bdd71bb96
Author: Josh Lavin <jlavin at endpoint.com>
Date: Mon Nov 16 17:01:12 2015 -0800
Use bcrypt in Strap demo
* Show demo user credentials while in demo mode
* Warnings about pepper
* Rework password reset to change password and set (plain), then
login user (promotes from_plain), then user can change their
password without knowing the old one (we set from what we changed
it to earlier). The initial set also invalidates the emailed link.
dist/strap/README | 10 +++++++++-
dist/strap/catalog.cfg | 14 +++++++++++---
dist/strap/pages/login.html | 20 ++++++++++++++++++++
dist/strap/pages/member/get_password.html | 12 ++++++------
dist/strap/pages/query/pw_reset.html | 23 ++++++++++-------------
5 files changed, 56 insertions(+), 23 deletions(-)
---
diff --git a/dist/strap/README b/dist/strap/README
index 57ecbae..48e805e 100644
--- a/dist/strap/README
+++ b/dist/strap/README
@@ -17,6 +17,8 @@ The Bootstrap and jQuery files are loaded from `variables/CSS` and
Works best with Interchange version 5.8.1 or higher.
+Requires installation of Bundle::Interchange CPAN module.
+
## Usage
`bin/makecat [your-catalog-name]`
@@ -28,6 +30,12 @@ Note: if you previously installed the "standard" template, you should
## Notes
+* **TURN OFF the MV_DEMO_MODE variable before using this in production!**
+
+* User passwords are crypted by default, using bcrypt. You *should*
+ change the "pepper" to something unique and random for your catalog.
+ Search for "pepper" in catalog.cfg.
+
* If you want stock alerting, you need to add a cronjob for the user of
your catalog, to run the 'daily' Interchange job. Something like:
@@ -62,7 +70,7 @@ Note: if you previously installed the "standard" template, you should
* Password Reset page no longer emails password (bad practice). Now
sends a basic encoded link to reset the password, which expires in 1
- day. Requires installation of Bundle::Interchange CPAN module.
+ day.
* Checkout pages have a ton of clean up, and improved with user-experience
guidelines for Checkout from Baymard Institute.
diff --git a/dist/strap/catalog.cfg b/dist/strap/catalog.cfg
index 576267f..8729aab 100644
--- a/dist/strap/catalog.cfg
+++ b/dist/strap/catalog.cfg
@@ -255,9 +255,17 @@ Pragma no_html_comment_embed
# User session related settings.
# Whether to encrypt passwords in UserDB
-# We usually don't for users, so we can mail them their password
-# We DO in admin, that is set in catalog_after.cfg
-UserDB default crypt 0
+UserDB default crypt 1
+UserDB default bcrypt 1
+
+# These 2 lines are needed for query/pw_reset
+UserDB default promote 1
+UserDB default from_plain 1
+
+# The pepper should be unique for your site, but note that if you change this,
+# it will make previously-crypted passwords inaccessible --
+# so set this before you start adding users, or don't set at all.
+#UserDB default bcrypt_pepper CHANGE_ME_255370299252265
# Set to 1 to make the username and password case-insensitive
UserDB default ignore_case 1
diff --git a/dist/strap/pages/login.html b/dist/strap/pages/login.html
index e7d5cb5..01f24b9 100644
--- a/dist/strap/pages/login.html
+++ b/dist/strap/pages/login.html
@@ -100,6 +100,26 @@ mv_username=email
</fieldset>
</form>
+ [if var MV_DEMO_MODE]
+ <div class="bg-info"><b>Demo mode:</b> try one of these default test users:</p><ul>
+ [loop acclist=1 list=|
+ kirk at icdevgroup.net=kirk,
+ devnull at icdevgroup.net=test,
+ king at icdevgroup.net=king,
+ Rollins at icdevgroup.net=rollins,
+ adams at icdevgroup.net=adams,
+ riley at icdevgroup.net=riley,
+ carter at icdevgroup.net=carter,
+ keller at icdevgroup.net=keller,
+ michael at icdevgroup.net=michaels,
+ smith at icdevgroup.net=smith,
+ milton at icdevgroup.net=test,
+ jones at icdevgroup.net=jones,
+ lucas at icdevgroup.net=lucas,
+ |]<li>[loop-code] ([loop-param label])</li>
+ [/loop]</ul></div>
+ [/if]
+
[else]
[bounce page="[either][ecgi destination][or]member/service[/either]"]
diff --git a/dist/strap/pages/member/get_password.html b/dist/strap/pages/member/get_password.html
index f85817a..d97f55d 100644
--- a/dist/strap/pages/member/get_password.html
+++ b/dist/strap/pages/member/get_password.html
@@ -30,14 +30,14 @@
subject="__COMPANY__ password reset"
from="__COMPANY__ <__EMAIL_SERVICE__>"][perl table=userdb]
$Tag->tmp('hmac');
- $Tag->tmp('expire');
+ $Tag->tmp('expires');
my $db = $Db{userdb};
my $uid = $Scratch->{found_user};
my $key = $Variable->{PASSWORD_RESET_CHECK_KEY};
- my $expire = $Scratch->{expire} = $Tag->time({ body => '%y%m%d%H', adjust => '1 days', });
- my ($email, $pw, $mod_time) = $db->get_slice($uid, ['email', 'password', 'mod_time']);
- # using mod_time in hmac prevents clicking link again after pw_reset page loads
- my $hmac = $Tag->filter({ op => "hmac_sha1_hex.$key", body => $mod_time . $expire . $email });
+ my $expires = $Scratch->{expires} = $Tag->time({ body => '%y%m%d%H', adjust => '1 days', });
+ my ($email, $pw, $mod_time, $expiry) = $db->get_slice($uid, [qw/email password mod_time expiration/]);
+ # using mod_time+expiry in hmac prevents clicking link again after pw_reset page loads
+ my $hmac = $Tag->filter({ op => "hmac_sha1_hex.$key", body => $mod_time . $expiry . $expires . $email });
$Scratch->{hmac} = substr($hmac, 0, 20); # cropping to fit in email; should be ok
return;
[/perl]Someone (maybe you) asked to reset the password for this member:
@@ -49,7 +49,7 @@ this email and nothing will happen.
[area href=query/pw_reset secure="__SECURE_ENABLE__" no_session=1 form="
u=[scratch found_user]
- x=[scratch expire]
+ x=[scratch expires]
k=[scratch hmac]
"]
diff --git a/dist/strap/pages/query/pw_reset.html b/dist/strap/pages/query/pw_reset.html
index 8f50a79..e3ea997 100644
--- a/dist/strap/pages/query/pw_reset.html
+++ b/dist/strap/pages/query/pw_reset.html
@@ -11,28 +11,25 @@
[and cgi k]
[userdb function=logout clear-cookie="MV_PASSWORD,MV_USERNAME" hide=1]
[perl table=userdb]
+ delete $Scratch->{key_matches};
my $uid = $CGI->{u};
- my $expire = $CGI->{x};
+ my $expires = $CGI->{x};
my $time = $Tag->time({ body => '%y%m%d%H' });
- return if ($expire < $time);
- # validated expiry, so keep going
+ return if ($expires < $time);
+ # validated expires, so keep going
my $db = $Db{userdb};
my $key = $Variable->{PASSWORD_RESET_CHECK_KEY};
- my ($email, $old_pw, $mod_time) = $db->get_slice($uid, ['email', 'password', 'mod_time']);
- # using mod_time in hmac prevents clicking link again after pw_reset page loads
- my $hmac = $Tag->filter({ op => "hmac_sha1_hex.$key", body => $mod_time . $expire . $email });
+ my ($email, $mod_time, $expiry) = $db->get_slice($uid, [qw/email mod_time expiration/]);
+ # using mod_time+expiry in hmac prevents clicking link again after pw_reset page loads
+ my $hmac = $Tag->filter({ op => "hmac_sha1_hex.$key", body => $mod_time . $expiry . $expires . $email });
+#Debug("k: " . $CGI->{k} . ", hmac: " . substr($hmac, 0, 20) );
if($CGI->{k} eq substr($hmac, 0, 20)) {
$Scratch->{key_matches} = 1;
- ## reset password and set expiration, just in case they don't change pwd now; invalidates key (increases mod_time)
+ # reset password and set expiration, just in case they don't change pwd now; invalidates key
my $new_pw;
for(1 .. 4) { $new_pw .= int(rand(10)); }
- my $cry_pw = $new_pw;
- if( $Config->{UserDB}{crypt} ) {
- $cry_pw = $Tag->crypt($new_pw);
- }
my $expire_pass = $Tag->time({ body => '%Y%m%d%H%M%S', adjust => '1 days', });
- $db->set_slice($uid, [qw/password expiration/], [$cry_pw, $expire_pass]);
-Log(qq{ pass for $uid was $old_pw, now $cry_pw } );
+ $db->set_slice($uid, [qw/password expiration/], [$new_pw, $expire_pass]);
$Scratch->{pwd} = $new_pw;
$Scratch->{email} = $email;
}
More information about the interchange-cvs
mailing list