[LON-CAPA-cvs] cvs: loncom / lond /auth lonauth.pm /enrollment localenroll.pm /html/adm/help/tex Domain_Configuration_LangTZAuth.tex /interface domainprefs.pm /lonnet/perl lonnet.pm

raeburn raeburn at source.lon-capa.org
Sat Feb 26 20:43:15 EST 2022


raeburn		Sun Feb 27 01:43:15 2022 EDT

  Modified files:              
    /loncom	lond 
    /loncom/auth	lonauth.pm 
    /loncom/interface	domainprefs.pm 
    /loncom/enrollment	localenroll.pm 
    /loncom/lonnet/perl	lonnet.pm 
    /loncom/html/adm/help/tex	Domain_Configuration_LangTZAuth.tex 
  Log:
  - Domain configuration to allow authentication of an alternate username, if
    username entered differs from real username in a predictable way,
    e.g., username entered in log-in page was email address (userid at example.tld)
    instead of just userid.
  
  
-------------- next part --------------
Index: loncom/lond
diff -u loncom/lond:1.574 loncom/lond:1.575
--- loncom/lond:1.574	Fri Feb 25 09:38:47 2022
+++ loncom/lond	Sun Feb 27 01:43:13 2022
@@ -2,7 +2,7 @@
 # The LearningOnline Network
 # lond "LON Daemon" Server (port "LOND" 5663)
 #
-# $Id: lond,v 1.574 2022/02/25 09:38:47 raeburn Exp $
+# $Id: lond,v 1.575 2022/02/27 01:43:13 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -65,7 +65,7 @@
 my $status='';
 my $lastlog='';
 
-my $VERSION='$Revision: 1.574 $'; #' stupid emacs
+my $VERSION='$Revision: 1.575 $'; #' stupid emacs
 my $remoteVERSION;
 my $currenthostid="default";
 my $currentdomainid;
@@ -259,6 +259,7 @@
                instidrules => {remote => 1, domroles => 1,},
                instrulecheck => {remote => 1, enroll => 1, reqcrs => 1, domroles => 1},
                instselfcreatecheck => {institutiononly => 1},
+               instunamemapcheck => {remote => 1,},  
                instuserrules => {remote => 1, enroll => 1, reqcrs => 1, domroles => 1},
                keys => {remote => 1,},
                load => {anywhere => 1},
@@ -312,6 +313,7 @@
                tmpget => {institutiononly => 1},
                tmpput => {remote => 1, othcoau => 1},
                tokenauthuserfile => {anywhere => 1},
+               unamemaprules => {remote => 1,},
                unsub => {content => 1,},
                update => {shared => 1},
                updatebalcookie => {institutiononly => 1},
@@ -2655,6 +2657,36 @@
     return;
 }
 
+sub inst_unamemap_check {
+    my ($cmd, $tail, $client)   = @_;
+    my $userinput               = "$cmd:$tail";
+    my %rulecheck;
+    my $outcome;
+    my ($udom,$uname, at rules) = split(/:/,$tail);
+    $udom = &unescape($udom);
+    $uname = &unescape($uname);
+    @rules = map {&unescape($_);} (@rules);
+    eval {
+        local($SIG{__DIE__})='DEFAULT';
+        $outcome = &localenroll::unamemap_check($udom,$uname,\@rules,\%rulecheck);
+    };
+    if (!$@) {
+        if ($outcome eq 'ok') {
+            my $result='';
+            foreach my $key (keys(%rulecheck)) {
+                $result.=&escape($key).'='.&Apache::lonnet::freeze_escape($rulecheck{$key}).'&';
+            }
+            &Reply($client,\$result,$userinput);
+        } else {
+            &Reply($client,"error\n", $userinput);
+        }
+    } else {
+        &Failure($client,"unknown_cmd\n",$userinput);
+    }
+}
+&register_handler("instunamemapcheck",\&inst_unamemap_check,0,1,0);
+
+
 #
 #   Determines if this is the home server for a user.  The home server
 #   for a user will have his/her lon-capa passwd file.  Therefore all we need
@@ -6806,6 +6838,39 @@
 }
 &register_handler("instemailrules",\&get_institutional_selfcreate_rules,0,1,0);
 
+sub get_unamemap_rules {
+    my ($cmd, $tail, $client)   = @_;
+    my $userinput               = "$cmd:$tail";
+    my $dom = &unescape($tail);
+    my (%rules_hash, at rules_order);
+    my $outcome;
+    eval {
+        local($SIG{__DIE__})='DEFAULT';
+        $outcome = &localenroll::unamemap_rules($dom,\%rules_hash,\@rules_order);
+    };
+    if (!$@) {
+        if ($outcome eq 'ok') {
+            my $result;
+            foreach my $key (keys(%rules_hash)) {
+                $result .= &escape($key).'='.&Apache::lonnet::freeze_escape($rules_hash{$key}).'&';
+            }
+            $result =~ s/\&$//;
+            $result .= ':';
+            if (@rules_order > 0) {
+                foreach my $item (@rules_order) {
+                    $result .= &escape($item).'&';
+                }
+            }
+            $result =~ s/\&$//;
+            &Reply($client,\$result,$userinput);
+        } else {
+            &Reply($client,"error\n", $userinput);
+        }
+    } else {
+        &Failure($client,"unknown_cmd\n",$userinput);
+    }
+}
+&register_handler("unamemaprules",\&get_unamemap_rules,0,1,0);
 
 sub institutional_username_check {
     my ($cmd, $tail, $client)   = @_;
@@ -8390,7 +8455,7 @@
                 #
                 # Don't attempt authentication for username and password supplied
                 # for user without an account if uername contains @ to avoid
-                # call to &Authen::Krb5::parse_name() which will result in con_lost 
+                # call to &Authen::Krb5::parse_name() which will result in con_lost
                 #
                 unless ($user =~ /\@/) {
                     $howpwd = $domdefaults{'auth_def'};
Index: loncom/auth/lonauth.pm
diff -u loncom/auth/lonauth.pm:1.171 loncom/auth/lonauth.pm:1.172
--- loncom/auth/lonauth.pm:1.171	Wed Nov 24 20:15:15 2021
+++ loncom/auth/lonauth.pm	Sun Feb 27 01:43:13 2022
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # User Authentication Module
 #
-# $Id: lonauth.pm,v 1.171 2021/11/24 20:15:15 raeburn Exp $
+# $Id: lonauth.pm,v 1.172 2022/02/27 01:43:13 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -583,9 +583,33 @@
 # --------------------------------------------------------------------- Failed?
 
     if ($authhost eq 'no_host') {
-	&failed($r,'Username and/or password could not be authenticated.',
-		\%form,$authhost);
-        return OK;
+        my $pwdverify;
+        if (&Apache::lonnet::homeserver($form{'uname'},$form{'udom'}) eq 'no_host') {
+            my %possunames = &alternate_unames_check($form{'uname'},$form{'udom'});
+            if (keys(%possunames) > 0) {
+                foreach my $rulematch (keys(%possunames)) {
+                    my $possuname = $possunames{$rulematch};
+                    if (($possuname ne '') && ($possuname =~ /^$match_username$/)) {
+                        $authhost=Apache::lonnet::authenticate($possuname,$upass,
+                                                               $form{'udom'},undef,
+                                                               $clientcancheckhost);
+                        if (($authhost eq 'no_host') || ($authhost eq 'no_account_on_host')) {
+                            next;
+                        } elsif (($authhost ne '') && (&Apache::lonnet::hostname($authhost) ne '')) {
+                            $pwdverify = 1;
+                            &Apache::lonnet::logthis("Authenticated user: $possuname was submitted as: $form{'uname'}"); 
+                            $form{'uname'} = $possuname;
+                            last;
+                        }
+                    }
+                }
+            }
+        }
+        unless ($pwdverify) {
+            &failed($r,'Username and/or password could not be authenticated.',
+                    \%form,$authhost);
+            return OK;
+        }
     } elsif ($authhost eq 'no_account_on_host') {
         if ($defaultauth) {
             my $domdesc = &Apache::lonnet::domain($form{'udom'},'description');
@@ -1086,6 +1110,20 @@
     return;
 }
 
+sub alternate_unames_check {
+    my ($uname,$udom) = @_;
+    my %possunames;
+    my %domdefs = &Apache::lonnet::get_domain_defaults($udom);
+    if (ref($domdefs{'unamemap_rule'}) eq 'ARRAY') { 
+        if (@{$domdefs{'unamemap_rule'}} > 0) {
+            %possunames =
+                &Apache::lonnet::inst_rulecheck($udom,$uname,undef,
+                                                'unamemap',$domdefs{'unamemap_rule'});
+        }
+    }
+    return %possunames;
+}
+
 1;
 __END__
 
Index: loncom/interface/domainprefs.pm
diff -u loncom/interface/domainprefs.pm:1.408 loncom/interface/domainprefs.pm:1.409
--- loncom/interface/domainprefs.pm:1.408	Fri Feb 18 13:39:22 2022
+++ loncom/interface/domainprefs.pm	Sun Feb 27 01:43:14 2022
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Handler to set domain-wide configuration settings
 #
-# $Id: domainprefs.pm,v 1.408 2022/02/18 13:39:22 raeburn Exp $
+# $Id: domainprefs.pm,v 1.409 2022/02/27 01:43:14 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -327,7 +327,9 @@
                       header => [{col1 => 'Setting',
                                   col2 => 'Value'},
                                  {col1 => 'Institutional user types',
-                                  col2 => 'Name displayed'}],
+                                  col2 => 'Name displayed'},
+                                 {col1 => 'Mapping for missing usernames via standard log-in',
+                                  col2 => 'Rules in use'}],
                       print => \&print_defaults,
                       modify => \&modify_defaults,
                     },
@@ -983,7 +985,7 @@
         if (($action eq 'autoupdate') || ($action eq 'usercreation') ||
             ($action eq 'selfcreation') || ($action eq 'selfenrollment') ||
             ($action eq 'usersessions') || ($action eq 'coursecategories') || 
-            ($action eq 'trust') || ($action eq 'contacts') ||
+            ($action eq 'trust') || ($action eq 'contacts') || ($action eq 'defaults') ||
             ($action eq 'privacy') || ($action eq 'passwords') || ($action eq 'lti')) {
             if ($action eq 'coursecategories') {
                 $output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);
@@ -1071,8 +1073,8 @@
             }
             $rowtotal ++;
         } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') ||
-                 ($action eq 'defaults') || ($action eq 'directorysrch') ||
-                 ($action eq 'helpsettings') || ($action eq 'wafproxy')) {
+                 ($action eq 'directorysrch') || ($action eq 'helpsettings') ||
+                 ($action eq 'wafproxy')) {
             $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'scantron') {
             $output .= $item->{'print'}->($r,'bottom',$dom,$confname,$settings,\$rowtotal);
@@ -10467,7 +10469,7 @@
                    'username' => 'new usernames',
                    'id'       => 'IDs',
                );
-    unless ($type eq 'email') {
+    unless (($type eq 'email') || ($type eq 'unamemap')) {
         my $css_class = $rowcount%2?' class="LC_odd_row"':'';
         $output = '<tr '.$css_class.'>'.
                   '<td><span class="LC_nobreak">'.
@@ -10522,9 +10524,9 @@
     } elsif ($colsleft == 1) {
         $output .= '<td class="LC_left_item"> </td>';
     }
-    $output .= '</tr></table>';
-    unless ($type eq 'email') {
-        $output .= '</td></tr>';
+    $output .= '</tr>';
+    unless (($type eq 'email') || ($type eq 'unamemap')) {
+        $output .= '</table></td></tr>';
     }
     return $output;
 }
@@ -10667,7 +10669,7 @@
             $datatable .= '</td></tr>';
             $rownum ++;
         }
-    } else {
+    } elsif ($position eq 'middle') {
         my %defaults;
         if (ref($settings) eq 'HASH') {
             if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {
@@ -10717,6 +10719,22 @@
                 $rownum ++;
             }
         }
+    } else {
+        my ($unamemaprules,$ruleorder) =
+            &Apache::lonnet::inst_userrules($dom,'unamemap');
+        $css_class = $rownum%2?' class="LC_odd_row"':'';
+        if ((ref($unamemaprules) eq 'HASH') && (ref($ruleorder) eq 'ARRAY')) {
+            my $numinrow = 2;
+            $datatable .= '<tr'.$css_class.'><td>'.&mt('Available conversions').'</td><td><table>'.
+                          &user_formats_row('unamemap',$settings,$unamemaprules,
+                                            $ruleorder,$numinrow).
+                          '</table></td></tr>';
+        }
+        if ($datatable eq '') {
+            $datatable .= '<tr'.$css_class.'><td colspan="2">'.
+                          &mt('No rules set for domain in customized localenroll.pm').
+                          '</td></tr>';
+        }
     }
     $$rowtotal += $rownum;
     return $datatable;
@@ -19972,6 +19990,41 @@
             $newvalues{$item} = $staticdefaults{$item};
         }
     }
+    my ($unamemaprules,$ruleorder);
+    my @possunamemaprules = &Apache::loncommon::get_env_multiple('form.unamemap_rule');
+    if (@possunamemaprules) {
+        ($unamemaprules,$ruleorder) =
+            &Apache::lonnet::inst_userrules($dom,'unamemap');
+        if ((ref($unamemaprules) eq 'HASH') && (ref($ruleorder) eq 'ARRAY')) {
+            if (@{$ruleorder} > 0) {
+                my %possrules;
+                map { $possrules{$_} = 1; } @possunamemaprules;
+                foreach my $rule (@{$ruleorder}) {
+                    if ($possrules{$rule}) {
+                        push(@{$newvalues{'unamemap_rule'}},$rule);
+                    }
+                }
+            }
+        }
+    }
+    if (ref($domdefaults{'unamemap_rule'}) eq 'ARRAY') {
+        if (ref($newvalues{'unamemap_rule'}) eq 'ARRAY') {
+            my @rulediffs = &Apache::loncommon::compare_arrays($domdefaults{'unamemap_rule'},
+                                                               $newvalues{'unamemap_rule'});
+            if (@rulediffs) {
+                $changes{'unamemap_rule'} = 1;
+                $domdefaults{'unamemap_rule'} = $newvalues{'unamemap_rule'};
+            }
+        } elsif (@{$domdefaults{'unamemap_rule'}} > 0) {
+            $changes{'unamemap_rule'} = 1;
+            delete($domdefaults{'unamemap_rule'});
+        }
+    } elsif (ref($newvalues{'unamemap_rule'}) eq 'ARRAY') {
+        if (@{$newvalues{'unamemap_rule'}} > 0) {
+            $changes{'unamemap_rule'} = 1;
+            $domdefaults{'unamemap_rule'} = $newvalues{'unamemap_rule'};
+        }
+    }
     my %defaults_hash = (
                          defaults => \%newvalues,
                         );
@@ -20086,6 +20139,26 @@
                             $resulttext .= '<li>'.&mt('Institutional user status types deleted').'</li>'; 
                         }
                     }
+                } elsif ($item eq 'unamemap_rule') {
+                    if (ref($newvalues{'unamemap_rule'}) eq 'ARRAY') {
+                        my @rulenames;
+                        if (ref($unamemaprules) eq 'HASH') {
+                            foreach my $rule (@{$newvalues{'unamemap_rule'}}) {
+                                if (ref($unamemaprules->{$rule}) eq 'HASH') {
+                                    push(@rulenames,$unamemaprules->{$rule}->{'name'});
+                                }
+                            }
+                        }
+                        if (@rulenames) {
+                            $resulttext .= '<li>'.&mt('Mapping for missing usernames includes: [_1]',
+                                                     '<ul><li>'.join('</li><li>', at rulenames).'</li></ul>').
+                                           '</li>';
+                        } else {
+                            $resulttext .= '<li>'.&mt('No mapping for missing usernames via standard log-in').'</li>';
+                        }
+                    } else {
+                        $resulttext .= '<li>'.&mt('Mapping for missing usernames via standard log-in deleted').'</li>';
+                    }
                 } else {
                     my $value = $env{'form.'.$item};
                     if ($value eq '') {
Index: loncom/enrollment/localenroll.pm
diff -u loncom/enrollment/localenroll.pm:1.63 loncom/enrollment/localenroll.pm:1.64
--- loncom/enrollment/localenroll.pm:1.63	Fri Jan 14 16:27:20 2022
+++ loncom/enrollment/localenroll.pm	Sun Feb 27 01:43:14 2022
@@ -1,6 +1,6 @@
 # functions to glue school database system into Lon-CAPA for 
 # automated enrollment
-# $Id: localenroll.pm,v 1.63 2022/01/14 16:27:20 raeburn Exp $
+# $Id: localenroll.pm,v 1.64 2022/02/27 01:43:14 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -1157,7 +1157,7 @@
 
 =pod
 
-=item get_multusersinfo
+=item get_multusersinfo()
 
  (a) $dom - domain
  (b) $type - username or id
@@ -1250,8 +1250,8 @@
                   keys of top level hash are short names  
                    (e.g., netid, noncredit) 
                   for each key, value is a hash
-                      desc => long name for rule  
-                      rule => description of rule
+                      name => long name for rule  
+                      desc => description of rule
                       authtype => (krb5,krb4,int, or loc)
                                  authentication type for rule 
                       authparm => authentication parameter for rule
@@ -1285,8 +1285,8 @@
                   keys of top level hash are short names
                    (e.g., netid, noncredit)
                   for each key, value is a hash
-                      desc => long name for rule
-                      rule => description of rule
+                      name => long name for rule
+                      desc => description of rule
 
  (c) $rulesorder - reference to array containing rule names
                    in order to be displayed
@@ -1312,8 +1312,8 @@
                   keys of top level hash are short names
                    (e.g., netid)
                   for each key, value is a hash
-                      desc => long name for rule
-                      rule => description of rule
+                      name => long name for rule
+                      desc => description of rule
 
  (c) $rulesorder - reference to array containing rule names
                    in order to be displayed
@@ -1331,6 +1331,46 @@
 
 =pod
 
+=item unamemap_rules()
+
+ Incoming data: three arguments
+ (a) $dom - domain
+ (b) $ruleshash - reference to hash containing rules
+                  (a hash of a hash)
+                  keys of top level hash are short names
+                   (e.g., netid)
+                  for each key, value is a hash
+                      name => long name for rule
+                      desc => description of rule
+
+ For example: 
+
+        %{$ruleshash} = (
+            emailaddress  => {
+                               name     => 'Email address to UserID',
+                               desc     => 'Extract userID from userID at example.tld',
+                             },
+                        );
+  would enable display of a checkbox for: 'Email address to UserID' in the
+  "Available conversions" item in the "Mapping for missing usernames via standard log-in"
+  panel available to a Domain Coordinator via:
+  Main Menu > Set domain configuration > Display ("Default authentication/language/timezone/portal/types" checked)
+
+ (c) $rulesorder - reference to array containing rule names
+                   in order to be displayed
+
+  returns 'ok' if no processing error.
+
+=cut
+
+sub unamemap_rules {
+    my ($dom,$ruleshash,$rulesorder) = @_;
+    my $outcome;
+    return $outcome;
+}
+
+=pod
+
 =item username_check() 
 
  Incoming data: four arguments
@@ -1338,7 +1378,7 @@
  (b) $uname - username to compare against rules (scalar)
  (c) $to_check (reference to array of rule names to check)
  (d) $resultshash (reference to hash of results)
-                    hash of results for rule checked
+                    hash of results for rules checked
                    - keys are rule names
                    - values are: 1 or 0 (for matched or unmatched) 
 
@@ -1362,7 +1402,7 @@
  (b) $id - ID to compare against rules (scalar)
  (c) $to_check (reference to array of rule names to check)
  (d) $resultshash (reference to hash of results)
-                    hash of results for rule checked
+                    hash of results for rules checked
                    - keys are rule names
                    - values are: 1 or 0 (for matched or unmatched)
 
@@ -1386,7 +1426,7 @@
  (b) $selfcreatename - e-mail proposed as username (compare against rules - scalar)
  (c) $to_check (reference to array of rule names to check)
  (d) $resultshash (reference to hash of results)
-                   hash of results for rule checked
+                   hash of results for rules checked
                    - keys are rule names
                    - values are: 1 or 0 (for matched or unmatched)
 
@@ -1403,6 +1443,44 @@
 
 =pod
 
+=item unamemap_check()
+
+ Incoming data: four arguments
+ (a) $dom - domain (scalar)
+ (b) $uname - username entered on log-in page (compare against rules - scalar)
+ (c) $to_check (reference to array of rule names to check)
+ (d) $resultshash (reference to hash of results)
+                   hash of results for rules checked
+                   - keys are rule names
+                   - values are derived username from substitution operation
+                     applied to $uname.
+
+  For example, in the msu domain the rule "msuemail" will replace an MSU
+  email address submitted as a username, with the part before the @msu.edu,
+  (known as the MSUNetID), which is what is used in LON-CAPA as a username.
+
+  if ($dom eq 'msu') {
+      foreach my $item (@{$to_check}) {
+          if ($item eq 'msuemail') {
+              if ($uname =~ /^(\w{2,8})\@msu\.edu$/) {
+                  $resultshash->{$item} = $1;
+              }
+          }
+      }
+   }
+
+ returns 'ok' if no processing error.
+
+=cut
+
+sub unamemap_check {
+    my ($dom,$uname,$to_check,$resultshash) = @_;
+    my $outcome;
+    return $outcome;
+}
+
+=pod
+
 =item AUTOLOAD()
 
  Incoming data: none
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.1483 loncom/lonnet/perl/lonnet.pm:1.1484
--- loncom/lonnet/perl/lonnet.pm:1.1483	Thu Feb 17 22:35:52 2022
+++ loncom/lonnet/perl/lonnet.pm	Sun Feb 27 01:43:14 2022
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.1483 2022/02/17 22:35:52 raeburn Exp $
+# $Id: lonnet.pm,v 1.1484 2022/02/27 01:43:14 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -1323,7 +1323,7 @@
 sub queryauthenticate {
     my ($uname,$udom)=@_;
     my $uhome=&homeserver($uname,$udom);
-    if (!$uhome) {
+    if ((!$uhome) || ($uhome eq 'no_host')) {
 	&logthis("User $uname at $udom is unknown when looking for authentication mechanism");
 	return 'no_host';
     }
@@ -1372,7 +1372,7 @@
     }
     if ($answer eq 'non_authorized') {
 	&logthis("User $uname at $udom rejected by $uhome");
-	return 'no_host'; 
+	return 'no_host';
     }
     &logthis("User $uname at $udom threw error $answer when checking authentication mechanism");
     return 'no_host';
@@ -2593,6 +2593,10 @@
                     $response=&unescape(&reply('instselfcreatecheck:'.
                                                &escape($udom).':'.&escape($uname).
                                               ':'.$rulestr,$homeserver));
+                } elsif ($item eq 'unamemap') {
+                    $response=&unescape(&reply('instunamemapcheck:'.
+                                               &escape($udom).':'.&escape($uname).
+                                              ':'.$rulestr,$homeserver));
                 }
                 if ($response ne 'refused') {
                     my @pairs=split(/\&/,$response);
@@ -2622,6 +2626,9 @@
             } elsif ($check eq 'email') {
                 $response=&reply('instemailrules:'.&escape($udom),
                                  $homeserver);
+            } elsif ($check eq 'unamemap') {
+                $response=&reply('unamemaprules:'.&escape($udom),
+                                 $homeserver); 
             } else {
                 $response=&reply('instuserrules:'.&escape($udom),
                                  $homeserver);
@@ -2680,6 +2687,7 @@
         $domdefaults{'intauth_cost'} = $domconfig{'defaults'}{'intauth_cost'};
         $domdefaults{'intauth_switch'} = $domconfig{'defaults'}{'intauth_switch'};
         $domdefaults{'intauth_check'} = $domconfig{'defaults'}{'intauth_check'};
+        $domdefaults{'unamemap_rule'} = $domconfig{'defaults'}{'unamemap_rule'};
     } else {
         $domdefaults{'lang_def'} = &domain($domain,'lang_def');
         $domdefaults{'auth_def'} = &domain($domain,'auth_def');
Index: loncom/html/adm/help/tex/Domain_Configuration_LangTZAuth.tex
diff -u loncom/html/adm/help/tex/Domain_Configuration_LangTZAuth.tex:1.12 loncom/html/adm/help/tex/Domain_Configuration_LangTZAuth.tex:1.13
--- loncom/html/adm/help/tex/Domain_Configuration_LangTZAuth.tex:1.12	Wed Jan  8 19:03:55 2020
+++ loncom/html/adm/help/tex/Domain_Configuration_LangTZAuth.tex	Sun Feb 27 01:43:14 2022
@@ -51,3 +51,35 @@
 \item \textit{Assignment to ``email-based'' usernames} Whether status type can also be assigned to a non-institutional user with an e-mail address as username
 \end{itemize}
 
+\textbf{Mapping for missing usernames via standard log-in} can be enabled for the domain via the same screen.
+
+For a user who logs-in to LON-CAPA via the standard log-in screen, customization is available to support credentials
+checking with an alternate username (but same password) if the username, as originally entered by the user, should
+be altered in a predictable way, to make it consistent with the format expected for usernames in the domain.
+
+An example is where an email address is supplied as the username by the user, but the part of the email address
+which precedes the @ in the email address is what is actually used in LON-CAPA for the user's username.
+
+A complication is the fact that a domain may support both types of username, e.g., userID, and userID at example.tld,
+as legitimate usernames for different types of user.  For example the usernames for official users may look like: userID,
+but privileged users may also create user accounts for guest users (including ``fictitous'' usernames for themselves, to
+use to test course behavior as a student) which look like: userID at example.tld.
+
+To accommodate that possibility, LON-CAPA will first attempt to authenticate the username and password, but if a user
+does not exist for the supplied username in the domain, can then see if a ``real'' username can be extracted from
+the one supplied, and make a second attempt to authenticate using the derived username with the password. Accordingly,
+authentication would fail for: userID at example.tld if that user did not exist, but might succeed for userID if that user
+did exist, and the password supplied matched what was expected.
+
+To enable this functionality requires customizing two routines in /home/httpd/lib/perl/localenroll.pm:
+&unamemap_rules() and &unamemap_check(). There are stubs for both of them (with documentation) in the
+uncustomized template file: /home/httpd/lib/perl/localenroll-std.pm.  Restart of loncontrol is required
+after making changes to localenroll.pm.
+
+Once &unamemap_rules() contains at least one rule, then the ``Default authentication/language/timezone/portal/types''
+domain configuration will include a checkbox for at least one rule in ``Available conversions'' listed in the
+``Mapping for missing usernames via standard log-in'' section. Checking the checkbox and pushing ``Save Changes''
+will make the corresponding conversion for that rule, as coded in &unamemap_check(), available to create
+a derived username for a second authentication attempt, if the original username did not exist, but matched
+the required format for the conversion.
+


More information about the LON-CAPA-cvs mailing list