[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