5

The application user has a lot of standard functionality we see in most applications. At a high-level, this includes some form of authentication, authorization, and session management. At a low-level, we have functions like:

  1. Checking the password strength;
  2. Hashing the password, perhaps with a bit of salt;
  3. Manipulating a hashmap of data tied to the session object;
  4. Checking if the user has a role that has the permission necessary to call a function.

Looking at Martin's Clean Architecture, I believe that the user high-level logic falls under use cases/application business rules. But do the details belong here as well?

For example, when a User registers or performs a login, the application needs to utilize best-practice algorithms, that should change as new attacks and vulnerabilities are discovered.

The request arrives from some UI and is handled by a controller at its first stop. Now, from a security perspective, we would want the password to be hashed as close to the entry point as possible, to reduce the severity of bugs that would leak the password into error messages, session data, logs, etc. This would mean that such functionality belongs in the controller. However, my understanding is that the controller is very thin and serves only as a proxy adapter between the UI and the application logic. As such, it shouldn't worry about complex operations such as hashing, but should focus on data translation and invoking the correct functions.

Now, at the use case layer, we might have a UserService class that offers a registerUser(username, password) function. The registerUser might have code such as:

registerUser(username, password) {
 if(isNotUnique(username)) throw new UserNameNotUniqueException();
 if(isNotStrong(password, username)) throw new InsufficientPasswordStrengthException();
 var password_hash = hashPassword(password);
 userRepo.save(new User(username, password_hash));

The isNotUnique calls the userRepository to retrieve a user with the given username. If the list is empty, the username is unique. The isNotStrong performs a series of checks for length, complexity, and similairty with the username. The hashPassword calls the latest and greatest library for performing the password hashing and supplies the strongest configuration parameters.

Ideally, we would have an adapter between the UserService and the PasswordHasher so that we can switch between implementations if the library becomes vulnerable. Would that make the PasswordHasher an interface adapter, while the actual library belongs to the Frameworks and Drivers layer?

My second question is how does all of this fit into the old MVC design? Would the user-related application logic fall inside the model? Is the MVC controller a similarly thin layer as Martin's interface adapter layer?

Third, would access control logic be more suitable at the application logic layer, instead of the controllers?

Finally, I would welcome comments and corrections for all the reasoning given above.

Christophe
82k11 gold badges135 silver badges202 bronze badges
asked Apr 23, 2020 at 7:49

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.