Odan's tutorial - adding authentication

Hi,

I just want to check I’m generally on the right path with this and my (untested) code is decent.

Also as I’ve added the selectUser method in /src/Domain/User/Repository/UserCreatorRepository.php I’m not sure its the best place for it. Should this be in another file called UserFinderRepository.php or should I have both methods in the same class named UserRepository?

I’ve installed lcobucci/jwt and I’m working through Odan’s tutorial. In src/Action/Auth/TokenCreateAction.php it has the following:

// Validate login (pseudo code) 
// Warning: This should be done in an application service and not here! 
// $userAuthData = $this->userAuth->authenticate($username, $password); 
$isValidLogin = ($username === 'user' && $password === 'secret');

if (!$isValidLogin) {
     // Invalid authentication credentials 
    return $response ->withHeader('Content-Type', 'application/json') ->withStatus(401, 'Unauthorized'); 
}

So I have attempted to implement this:

   $userAuthData = $this->userAuth->authenticate($username, $password); 
   
   if (isset($userAuthData['error']))
   { // Invalid authentication credentials 
    	return $response ->withHeader('Content-Type', 'application/json')
    	                 ->withStatus(401, 'Unauthorized'); 
   }

My UserAuth class:

<?php
namespace App\Domain\User\Service;
use App\Domain\User\Repository\UserCreatorRepository; 
use App\Exception\ValidationException;

/** 
 * Service. 
 */ 

final class UserAuth { 
	/** 
	 * @var UserCreatorRepository 
	 */ 
	private $repository;

	/**
	 * The constructor. 
	 * 
	 * @param UserCreatorRepository $repository The repository 
	 */ 

 	public function __construct(UserCreatorRepository $repository) {
 		$this->repository = $repository; 
 	}

	/*
	 *	@param String $username, String $password 
	 *  return Array (associative)
	 */
 	public function authenticate(String $username, String $password) : array {
 	 	$user = $this->repository->selectUser(String $username, String $password);
 	 	
 	 	if(!isset($user['username'])) {
 	 	 	$user['error'] = 'user ' . $username . ' not found.';
 	 	}

 	 	return $user;
 	}

} 

I added the selectUser method in /src/Domain/User/Repository/UserCreatorRepository.php:

public function selectUser(String $username, String $password): array { 
    $user = array();
    $sql = "SELECT username, first_name, last_name, email FROM users WHERE username = ? AND password = ? LIMIT 1";
    if($stmt = $this->connection->prepare($sql)) {

       $stmt->bind_param("username", $username); 
       $stmt->bind_param("password", $password); 
       $stmt->execute(); 

       /* bind variables to prepared statement */
        $stmt->bind_result($username, $first_name, $last_name, $email);

       if($stmt->fetch()) {
           $user['username'] = $username;
           $user['first_name'] = $first_name;
           $user['last_name'] = $last_name;
           $user['email'] = $email;
       }

       $stmt->close();        
    }

    return $user;
}

Thank you

I would add a dedicated Repository class for the Service. For Example, when the Service class name is UserAuth, then the Repository class name would be UserAuthRepository.

Thank you very much, I’ll look into that. I had some other issues with my selectUser function, I’ve resolved that now though.

Sincerely appreciate all your replies! I’m enjoying code again too!

1 Like