Tjirp
Tjirp

Reputation: 2455

Who/what authenticates a user PHP OO

getting in another discussion at work here about how to authenticate, or more likely. Who should authenticate a user.

Given the following code examples:

<?php
class User {
  public function isValid($username, $password) {
      //Logic to check if username/password match
      $this->setId($id);
  }
}

vs.

 <?php
 class Auth {
    public function isValid($username, $password) { 
      //Logic to check if username/password match
      $user = new User;
      $user->setId($id);
      return $user;
    }
  }

I personnaly give the following example why in this case #1 is bad: If a user is allowed to authenticate themself. And they would walk into a movie theater. They can just walk into any movie. Just saying to themselves they are valid.

Where the second example has an external object checking for the validity of the user. Thus being more "oop"

Mind you I have no education in OOP programming and this is probably something I read back in '08 or '09 when I started coding :) I hope some people here know what I mean and can then explain what are the good/bad practices here.

Thanks in progress

Upvotes: 1

Views: 246

Answers (3)

koen
koen

Reputation: 13737

You are right in that it is not very common for a person to authenticate himself when eg going to a movie. In you're argument with your co-workers you may want to generalize this:

Who is responsible for authenticating a user?

This is a question you can ask yourself every time you seem stuck on a design question. I'm not saying it's the one rule that will answer all your questions, but it clears troubled vision in a lot of situations and your question is an excellent example.

You also may want to read this text:

http://lizkeogh.com/2009/07/01/pixie-driven-development/

Upvotes: 0

Gordon
Gordon

Reputation: 316939

The logic should not be on the User for two reasons:

  1. it couples the logic to authenticate with a certain backend to the user
  2. the method operates on external arguments instead of object members.

Now, you could decouple the authentication logic (1) and work on object members (2) by doing

class User … 
    public function authenticate(Authenticable $adapter)
    {
        $this->isAuthenticated = $adapter->authenticate(
            array(
                'username' => $this->username,
                'password' => $this->password,
            )
        );
    }
}

but this bears the question why (and how) password should be stored on the User at all. You surely dont want to have the cleartext there. And hashing the password is not the responsibility of the User in my opinion. In fact, you cannot hash it in the User if you dont also add the salt to the User and that's something I would not think of a typical User property. You could hash the password to rehash it with a salt in the $adapter, but that is only curing symptoms. In OOP, Object Methods should operate on the members of an object. But if password shouldnt be a member of the User in the first place, the method using it shouldn't be on User either (cohesion).

Needless to say, if you are using ActiveRecord, you will likely have something like the above or have the authentication method as a static method on the User that will then return an instance. Personally, I dont like AR and static methods, so I'd go with a separate Authentication Service class that returns Users for me.

Upvotes: 2

akamike
akamike

Reputation: 2158

Your User object would be a model for a user profile, holding details such as username, password, email, etc. However, you can theoretically have a profile on a site without linking that to a login (perhaps there is only one master administrator who can edit profiles).

Your Auth class would handle the login check as I imagine that would also deal with setting and removing user sessions, which are separate from the actual user profile.

  • User = Model for user data
  • Auth = Logic for authentication

Think of it this way, if you decided to change how your profile authentication works (perhaps removing your own login process and replacing it with Twitter OAuth), separating your authentication logic from your user profile could make this easier.

Upvotes: 1

Related Questions