1 // This may look like C code, but it's really -*- C++ -*-
2 /*
3  * Copyright (C) 2011 Emweb bv, Herent, Belgium.
4  *
5  * See the LICENSE file for terms of use.
6  */
7 #ifndef WT_AUTH_ABSTRACT_PASSWORD_AUTH_H_
8 #define WT_AUTH_ABSTRACT_PASSWORD_AUTH_H_
9 
10 #include <Wt/WValidator.h>
11 #include <Wt/WString.h>
12 
13 #include <Wt/Auth/User.h>
14 
15 namespace Wt {
16   namespace Auth {
17 
18 class AuthService;
19 class User;
20 
21 /*! \brief Enumeration for a password verification result
22  *
23  * \sa AbstractPasswordService::verifyPassword()
24  *
25  * \ingroup auth
26  */
27 enum class PasswordResult {
28   PasswordInvalid, //!< The password is invalid
29   LoginThrottling, //!< The attempt was not processed because of throttling
30   PasswordValid    //!< The password is valid
31 };
32 
33 /*! \class AbstractPasswordService Wt/Auth/AbstractPasswordService.h
34  *  \brief Abstract password authentication service
35  *
36  * This abstract class defines the interface for password authentication.
37  *
38  * It provides methods to verify a password, to update a password, and to
39  * throttle password verification attempts.
40  *
41  * \sa PasswordService a default implementation
42  *
43  * \ingroup auth
44  */
45 class WT_API AbstractPasswordService
46 {
47 public:
48   /*! \class StrengthValidatorResult
49    *  \brief Result returned when validating password strength.
50    *
51    * This class contains information on the validity and the strength of
52    * the password together with possible messages.
53    * When the password is considered not strong enough, a message should
54    * be provided which helps the user pick a stronger password.
55    *
56    * \sa AbstractStrengthValidator::evaluateStrength()
57    */
58   class StrengthValidatorResult {
59   public:
60     /*! \brief Constructor.
61      */
62     StrengthValidatorResult(bool valid,
63 			    const WString &message,
64 			    int strength);
65 
66     /*! \brief Returns whether the password is considered strong enough.
67      */
isValid()68     bool isValid() { return valid_; }
69 
70     /*! \brief Returns a message describing the password strength.
71      */
message()72     WString message() { return message_; }
73 
74     /*! \brief Returns the password strength in a scale of 0 to 5.
75      */
strength()76     int strength() { return strength_; }
77 
78   private:
79     bool valid_;
80     WString message_;
81     int strength_;
82   };
83 
84   /*! \class AbstractStrengthValidator
85    *  \brief Validator for password strength.
86    *
87    * This class defines a specialized validator interface for evaluating
88    * password strength. The implementation allows to evaluate strength
89    * in addition to the normal validator functionality of validating a
90    * password.
91    *
92    * The evaluateStrength() computes the strength and returns
93    * an instance of StrenghtValidatorResult which contains information on the
94    * validity and the strength of the password together with possible messages.
95    *
96    * \sa strengthValidator()
97    */
98   class WT_API AbstractStrengthValidator : public Wt::WValidator
99   {
100   public:
101     /*! \brief Constructor.
102      */
103     AbstractStrengthValidator();
104 
105     /*! \brief Evaluates the strength of a password.
106      *
107      * The result is an instance of StrengthValidatorResult which
108      * contains information on the validity and the strength of the password
109      * together with possible messages.
110      *
111      * The validator may take into account the user's login name and
112      * email address, to exclude passwords that are too similar to
113      * these.
114      */
115     virtual StrengthValidatorResult
116       evaluateStrength(const WT_USTRING& password,
117 		       const WT_USTRING& loginName,
118 		       const std::string& email) const = 0;
119 
120     /*! \brief Validates a password.
121      *
122      * This uses evaluateStrength(), isValid() and message() to return the
123      * result of password validation.
124      */
125     virtual Result validate(const WT_USTRING& password,
126 			    const WT_USTRING& loginName,
127 			    const std::string& email) const;
128 
129     /*! \brief Validates a password.
130      *
131      * Calls validate(password, WString::Empty, "");
132      */
133     virtual Result validate(const WT_USTRING& password) const override;
134   };
135 
136   /*! \brief Destructor.
137    */
138   virtual ~AbstractPasswordService();
139 
140   /*! \brief Returns the basic authentication service.
141    */
142   virtual const AuthService& baseAuth() const = 0;
143 
144   /*! \brief Returns whether password attempt throttling is enabled.
145    */
146   virtual bool attemptThrottlingEnabled() const = 0;
147 
148   /*! \brief Returns a validator which checks that a password is strong enough.
149    */
150   virtual AbstractStrengthValidator *strengthValidator() const = 0;
151 
152   /*! \brief Returns the delay for this user for a next authentication
153    *         attempt.
154    *
155    * If password attempt throttling is enabled, then this returns the
156    * number of seconds this user must wait for a new authentication
157    * attempt, presumably because of a number of failed attempts.
158    *
159    * \sa attemptThrottlingEnabled()
160    */
161   virtual int delayForNextAttempt(const User& user) const = 0;
162 
163   /*! \brief Verifies a password for a given user.
164    *
165    * The supplied password is verified against the user's credentials
166    * stored in the database. If password account throttling is
167    * enabled, it may also refuse an authentication attempt.
168    *
169    * \sa setVerifier(), setAttemptThrottlingEnabled()
170    */
171   virtual PasswordResult verifyPassword(const User& user,
172 					const WT_USTRING& password) const = 0;
173 
174   /*! \brief Sets a new password for the given user.
175    *
176    * This stores a new password for the user in the database.
177    */
178   virtual void updatePassword(const User& user, const WT_USTRING& password)
179     const = 0;
180 };
181 
182   }
183 }
184 
185 #endif // WT_AUTH_ABSTRACT_PASSWORD_AUTH
186