From 3346f0c243c52b56cb6e9a85af58fa6f3acd673c Mon Sep 17 00:00:00 2001
From: Jan-Hendrik Willms <tleilax+studip@gmail.com>
Date: Wed, 26 Oct 2022 19:34:43 +0000
Subject: [PATCH] adjust password reset links expiration to 1 week and include
 expiration info in sent mails, fixes #1647

Closes #1647

Merge request studip/studip!1061
---
 lib/classes/UserManagement.class.php | 29 ++++++++++++++++++++--------
 lib/models/Token.php                 | 18 ++++++++++++-----
 2 files changed, 34 insertions(+), 13 deletions(-)

diff --git a/lib/classes/UserManagement.class.php b/lib/classes/UserManagement.class.php
index 2ab2f87bf5f..236318bbb3b 100644
--- a/lib/classes/UserManagement.class.php
+++ b/lib/classes/UserManagement.class.php
@@ -679,7 +679,14 @@ class UserManagement
         setTempLanguage($user->user_id);
 
         // always generate a token, so root, admin and all other users profit from the abuse protection
-        $id = Token::create(24 * 60 * 60, $user->id);
+        if ($new) {
+            $expiration_in_hours = 24;
+            $spoken_expiration = _('24 Stunden');
+        } else {
+            $expiration_in_hours = 7 * 24;
+            $spoken_expiration = _('eine Woche');
+        }
+        $token = Token::create($expiration_in_hours * 60 * 60, $user->id, true);
 
         // new users alawys receive a link to generate a password
         if ($new) {
@@ -690,20 +697,23 @@ class UserManagement
 
             $mailbody = sprintf(
                 _("Dies ist eine Bestätigungsmail des Stud.IP-Systems\n"
-                    ."(Studienbegleitender Internetsupport von Präsenzlehre)\n- %s -\n\n"
+                    ."(Studienbegleitender Internetsupport von Präsenzlehre)\n- %1\$s -\n\n"
                     ."Es wurde für sie ein Zugang zum System erstellt, Ihr Nutzername lautet:\n\n"
-                    ."%s\n\n"
+                    ."%2\$s\n\n"
                     ."Um den Zugang nutzen zu können, müssen sie ein Passwort setzen.\n"
                     ."Öffnen Sie dafür bitte folgenden Link\n\n"
-                    ."%s\n\n"
+                    ."%3\$s\n\n"
                     ."in Ihrem Browser.\n\n"
+                    ."Der Link ist %4\$s (bis %5\$s) gültig.\n\n"
                     ."Wahrscheinlich unterstützt Ihr E-Mail-Programm ein einfaches Anklicken des Links.\n"
                     ."Ansonsten müssen Sie Ihren Browser öffnen und den Link komplett in die Zeile\n"
                     ."\"Location\" oder \"URL\" kopieren.\n\n"
                 ),
                 Config::get()->UNI_NAME_CLEAN,
                 $user->username,
-                $GLOBALS['ABSOLUTE_URI_STUDIP'] . 'dispatch.php/new_password/set/'. $id .'?cancel_login=1'
+                $GLOBALS['ABSOLUTE_URI_STUDIP'] . 'dispatch.php/new_password/set/'. $token->token .'?cancel_login=1',
+                $spoken_expiration,
+                strftime('%x %X', $token->expiration)
             );
         } else
 
@@ -738,14 +748,15 @@ class UserManagement
 
             $mailbody = sprintf(
                 _("Dies ist eine Bestätigungsmail des Stud.IP-Systems\n"
-                    ."(Studienbegleitender Internetsupport von Präsenzlehre)\n- %s -\n\n"
+                    ."(Studienbegleitender Internetsupport von Präsenzlehre)\n- %1\$s -\n\n"
                     ."Sie haben um die Zurücksetzung Ihres Passwortes gebeten.\n\n"
                     ."Diese E-Mail wurde Ihnen zugesandt um sicherzustellen,\n"
                     ."dass die angegebene E-Mail-Adresse tatsächlich Ihnen gehört.\n\n"
                     ."Wenn Sie um die Zurücksetzung Ihres Passwortes gebeten haben,\n"
                     ."dann öffnen Sie bitte folgenden Link\n\n"
-                    ."%s\n\n"
+                    ."%2\$s\n\n"
                     ."in Ihrem Browser. Auf der Seite können Sie ein neues Passwort setzen.\n\n"
+                    ."Der Link ist %3\$s (bis %4\$s) gültig.\n\n"
                     ."Wahrscheinlich unterstützt Ihr E-Mail-Programm ein einfaches Anklicken des Links.\n"
                     ."Ansonsten müssen Sie Ihren Browser öffnen und den Link komplett in die Zeile\n"
                     ."\"Location\" oder \"URL\" kopieren.\n\n"
@@ -756,7 +767,9 @@ class UserManagement
                     ."Änderungen an Ihren Zugangsdaten vorgenommen.\n\n"
                 ),
                 Config::get()->UNI_NAME_CLEAN,
-                $GLOBALS['ABSOLUTE_URI_STUDIP'] . 'dispatch.php/new_password/set/'. $id .'?cancel_login=1'
+                $GLOBALS['ABSOLUTE_URI_STUDIP'] . 'dispatch.php/new_password/set/'. $token->token .'?cancel_login=1',
+                $spoken_expiration,
+                strftime('%x %X', $token->expiration)
             );
         }
 
diff --git a/lib/models/Token.php b/lib/models/Token.php
index f2fd6fa683b..a42cf77b6f5 100644
--- a/lib/models/Token.php
+++ b/lib/models/Token.php
@@ -5,6 +5,13 @@
  * @author    Jan-Hendrik Willms <tleilax+studip@gmail.com>
  * @author    Marco Diedrich <mdiedric@uos.de>
  * @license   GPL2 or any later version
+ *
+ * @property string $id
+ * @property string $token
+ * @property string $user_id
+ * @property int $expiration
+ * @property int $mkdate
+ * @property User $user
  */
 class Token extends SimpleORMap
 {
@@ -44,18 +51,19 @@ class Token extends SimpleORMap
     /**
      * Creates a new token.
      *
-     * @param  integer $duration Lifetime of the token
-     * @param  mixed   $user_id  Optional id of the user (defaults to current user)
-     * @return string the token
+     * @param integer $duration       Lifetime of the token
+     * @param mixed   $user_id        Optional id of the user (defaults to current user)
+     * @param bool     $return_object Return the actual token object if true, only the token otherwise (default)
+     * @return string|Token the token
      */
-    public static function create($duration = 30, $user_id = null)
+    public static function create($duration = 30, $user_id = null, bool $return_object = false)
     {
         $token = new self();
         $token->user_id    = $user_id ?? $GLOBALS['user']->id;
         $token->expiration = strtotime("+{$duration} seconds");
         $token->store();
 
-        return $token->token;
+        return $return_object ? $token : $token->token;
     }
 
     /**
-- 
GitLab