[freeside-commits] branch master updated. 26ddb940ad27ce8ac5e87084eeed857a390987bc

Ivan Kohler ivan at freeside.biz
Wed Sep 7 17:22:52 PDT 2022


The branch, master has been updated
       via  26ddb940ad27ce8ac5e87084eeed857a390987bc (commit)
      from  691de38ac2ca6c54b37feb50e1332bab6268773f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 26ddb940ad27ce8ac5e87084eeed857a390987bc
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Wed Sep 7 17:22:51 2022 -0700

    google authenticator support, RT#86743

diff --git a/FS/FS/AuthCookieHandler.pm b/FS/FS/AuthCookieHandler.pm
index 93d8ea6a5..b7d0dbf5b 100644
--- a/FS/FS/AuthCookieHandler.pm
+++ b/FS/FS/AuthCookieHandler.pm
@@ -13,13 +13,13 @@ sub useragent_ip {
 }
 
 sub authen_cred {
-  my( $self, $r, $username, $password ) = @_;
+  my( $self, $r, $username, $password, $totp_code ) = @_;
 
   preuser_setup();
 
   my $info = {};
 
-  unless ( FS::Auth->authenticate($username, $password, $info) ) {
+  unless ( FS::Auth->authenticate($username, $password, $totp_code, $info) ) {
     warn "failed auth $username from ". $self->useragent_ip($r). "\n";
     return undef;
   }
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index d88403644..61b793bb4 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -5931,6 +5931,7 @@ sub tables_hashref {
         'username',           'varchar',     '', $char_d, '', '',
         '_password',          'varchar', 'NULL', $char_d, '', '',
         '_password_encoding', 'varchar', 'NULL', $char_d, '', '',
+        'totp_secret32',         'char', 'NULL',      32, '', '',
         'last',               'varchar', 'NULL', $char_d, '', '', 
         'first',              'varchar', 'NULL', $char_d, '', '', 
         'user_custnum',           'int', 'NULL',      '', '', '',
diff --git a/FS/FS/access_user.pm b/FS/FS/access_user.pm
index f23aa77f9..270f8bb27 100644
--- a/FS/FS/access_user.pm
+++ b/FS/FS/access_user.pm
@@ -13,6 +13,7 @@ use FS::agent;
 use FS::cust_main;
 use FS::sales;
 use Carp qw( croak );
+use Auth::GoogleAuth;
 
 $DEBUG = 0;
 $me = '[FS::access_user]';
@@ -239,6 +240,7 @@ sub check {
     $self->ut_numbern('usernum')
     || $self->ut_alpha_lower('username')
     || $self->ut_textn('_password')
+    || $self->ut_alphan('totp_secret32')
     || $self->ut_textn('last')
     || $self->ut_textn('first')
     || $self->ut_foreign_keyn('user_custnum', 'cust_main', 'custnum')
@@ -733,6 +735,44 @@ sub change_password_fields {
   FS::Auth->auth_class->change_password_fields( @_ );
 }
 
+=item google_auth
+
+=cut
+
+sub google_auth {
+  my( $self ) = @_;
+  my $issuer = FS::Conf->new->config('company_name'). ' Freeside';
+  my $label = $issuer. ':'. $self->username;
+
+  Auth::GoogleAuth->new({
+    secret => $self->totp_secret32,
+    issuer => $issuer,
+    key_id => $label,
+  });
+
+}
+
+=item set_totp_secret32
+
+=cut
+
+sub set_totp_secret32 {
+  my( $self ) = @_;
+
+  $self->totp_secret32( $self->google_auth->generate_secret32 );
+  $self->replace;
+}
+
+=item totp_qr_code_url
+
+=cut
+
+sub totp_qr_code_url {
+  my( $self ) = @_;
+
+  $self->google_auth->qr_code;
+}
+
 =item locale
 
 =cut
diff --git a/debian/control b/debian/control
index 479a150d1..043294fc8 100644
--- a/debian/control
+++ b/debian/control
@@ -109,7 +109,7 @@ Depends: aspell-en,gnupg,ghostscript,gsfonts,gzip,
  libspreadsheet-xlsx-perl, libpod-simple-perl, libwebservice-northern911-perl,
  liblocale-codes-perl, liblocale-po-perl, libgeo-uscensus-geocoding-perl,
  libnet-sftp-foreign-perl, libpdf-webkit-perl, libgeo-shapelib-perl,
- libgeo-json-perl
+ libgeo-json-perl, libauth-googleauth-perl
 Conflicts: libparams-classify-perl (>= 0.013-6)
 Replaces: freeside (<<4)
 Breaks: freeside (<<4)
diff --git a/httemplate/browse/access_user.html b/httemplate/browse/access_user.html
index 446bfe0be..658762763 100644
--- a/httemplate/browse/access_user.html
+++ b/httemplate/browse/access_user.html
@@ -49,6 +49,11 @@ my $groups_sub = sub {
 
 };
 
+my $goog_auth_sub = sub {
+  my $access_user = shift;
+  $access_user->totp_secret32 ? 'Enabled' : '';
+};
+
 my $installer_sub = sub {
   my $access_user = shift;
   my @sched_item = $access_user->sched_item or return '';
@@ -66,11 +71,23 @@ my $count_query = 'SELECT COUNT(*) FROM access_user';
 my $link = [ $p.'edit/access_user.html?', 'usernum' ];
 
 my @header = (
-  'Username', 'Full name', 'Groups',    'Installer',    'Customer' );
+  'Username',
+  'Full name',
+  'Groups',
+  'Google Auth',
+  'Installer',
+  'Customer',
+);
 my @fields = (
-  'username', 'name',      $groups_sub, $installer_sub, $cust_sub, );
-my $align = 'lllcl';
-my @links = ( $link, $link, $link, '', '', $cust_link );
+  'username',
+  'name',
+  $groups_sub,
+  $goog_auth_sub,
+  $installer_sub,
+  $cust_sub,
+);
+my $align = 'lllccl';
+my @links = ( $link, $link, $link, '', '', '', $cust_link );
 
 #if ( FS::Conf->new->config('ticket_system') ) {
 #  push @header, 'Ticketing';
diff --git a/httemplate/edit/process/access_user.html b/httemplate/edit/process/access_user.html
index c27262017..8e264c1a9 100644
--- a/httemplate/edit/process/access_user.html
+++ b/httemplate/edit/process/access_user.html
@@ -5,7 +5,7 @@
 <%   include( 'elements/process.html',
                  'table'          => 'access_user',
                  'viewall_dir'    => 'browse',
-                 'copy_on_empty'  => [ '_password', '_password_encoding' ],
+                 'copy_on_empty'  => [ '_password', '_password_encoding', 'totp_secret32' ],
                  'clear_on_error' => [ '_password', '_password2' ],
                  'process_m2m'    => { 'link_table'   => 'access_usergroup',
                                        'target_table' => 'access_group',
diff --git a/httemplate/loginout/login.html b/httemplate/loginout/login.html
index 72e9525c4..1785ea796 100644
--- a/httemplate/loginout/login.html
+++ b/httemplate/loginout/login.html
@@ -27,6 +27,10 @@
         <TD ALIGN="right">Password: </TD>
         <TD><INPUT TYPE="password" NAME="credential_1" SIZE="13"></TD>
       </TR>
+      <TR>
+        <TD ALIGN="right">One-time code: </TD>
+        <TD><INPUT TYPE="text" NAME="credential_2" SIZE="13"></TD>
+      </TR>
     </TABLE>
     <BR>
  
@@ -42,7 +46,7 @@
 my %error = (
   'no_cookie'       => '', #First login, don't display an error
   'bad_cookie'      => 'Bad Cookie', #timed out?
-  'bad_credentials' => 'Incorrect username / password',
+  'bad_credentials' => 'Incorrect username / password / one-time code',
   #'logout'          => 'You have been logged out.',
 );
 
diff --git a/httemplate/pref/pref.html b/httemplate/pref/pref.html
index 56fde6d44..5f68d3e46 100644
--- a/httemplate/pref/pref.html
+++ b/httemplate/pref/pref.html
@@ -29,6 +29,18 @@
     </TABLE>
     <BR>
 
+    <FONT CLASS="fsinnerbox-title"><% emt('Google Authenticator') %></FONT>
+    <TABLE CLASS="fsinnerbox">
+      <TR>
+%       if ( $curuser->totp_secret32 ) {
+          <TD><IMG SRC="<% $curuser->totp_qr_code_url %>"</IMG></TD>
+%       } else {
+          <TD><A HREF="<%$p%>pref/set_totp_secret32.html">Enable</A></TD>
+%       }
+      </TR>
+    </TABLE>
+    <BR>
+
 % }
 
 <FONT CLASS="fsinnerbox-title"><% emt("Interface") %></FONT>
diff --git a/httemplate/pref/set_totp_secret32.html b/httemplate/pref/set_totp_secret32.html
new file mode 100644
index 000000000..f5676bc38
--- /dev/null
+++ b/httemplate/pref/set_totp_secret32.html
@@ -0,0 +1,19 @@
+<& /elements/header.html, mt('Google Authenticator for [_1]', $FS::CurrentUser::CurrentUser->username) &>
+
+Scan this code with the Google Authenticator application on your phone.
+<BR><BR>
+
+<IMG SRC="<% $access_user->totp_qr_code_url %>"></IMG>
+<BR><BR>
+
+Future logins will require a 6-digit code generated by the application.
+
+<& /elements/footer.html &>
+<%init>
+
+my $access_user = $FS::CurrentUser::CurrentUser;
+
+my $error = $access_user->set_totp_secret32 unless length($access_user->totp_secret32);
+die $error if $error; #better error handling for this "shouldn't happen" case?
+
+</%init>

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/AuthCookieHandler.pm               |  4 ++--
 FS/FS/Schema.pm                          |  1 +
 FS/FS/access_user.pm                     | 40 ++++++++++++++++++++++++++++++++
 debian/control                           |  2 +-
 httemplate/browse/access_user.html       | 25 ++++++++++++++++----
 httemplate/edit/process/access_user.html |  2 +-
 httemplate/loginout/login.html           |  6 ++++-
 httemplate/pref/pref.html                | 12 ++++++++++
 httemplate/pref/set_totp_secret32.html   | 19 +++++++++++++++
 9 files changed, 102 insertions(+), 9 deletions(-)
 create mode 100644 httemplate/pref/set_totp_secret32.html




More information about the freeside-commits mailing list