Authentication
Authentication Flow
Authenticate using an account type
For this purpose we’ve created the Prest\Auth\Manager
which will store the session information for the duration of the request:
use Acme\Auth\AccountType\Username;
// Authenticate user using username and password (Username Account):
$session = $authManager->loginWithUsernamePassword(
UsernameAccountType::NAME,
$username,
$password
);
On failure it will throw Prest\Exception\AuthException
with Prest\Constants\ErrorCodes::AUTH_LOGIN_FAILED
error code.
Receive session
After we’ve successfully authenticated we retrieve the Prest\Auth\Session
which we then use to create a response.
/** @var \Prest\Auth\Session $session */
$session = $this->authManager->getSession();
$response = [
'token' => $session->getToken(),
'expires' => $session->getExpirationTime(),
];
Store session
Because REST applications are supposed to be stateless, the session needs to be stored on the client.
Make subsequent request using the stored session
We can now authenticate any further requests using the received token from the initial authentication.
The Prest\Auth\Manager::authenticateToken
will throw a new Prest\Exception\AuthException
with following status codes:
Code | Constant | HTTP Status Code | Message | Reason |
---|---|---|---|---|
2030 | AUTH_TOKEN_INVALID |
401 | Authentication: Token Invalid | An invalid token has been given. |
2040 | AUTH_SESSION_EXPIRED |
401 | Authentication: Session Expired | The session token has been expired. |
2050 | AUTH_SESSION_INVALID |
401 | Authentication: Session Invalid | Failed to authenticate with use of provided identity. |
/**
* @var \Prest\Http\Request $request
* @var \Prest\Auth\Manager $authManager
*/
if ($token = $this->request->getToken()) {
$this->authManager->authenticateToken($token);
}
We’ve already incorporated the logic above in it’s own piece of middleware. Read more on our middleware.
Configure AuthManager
namespace Acme\Provider\AuthManager;
use Acme\Auth\Manager;
use Phalcon\DiInterface;
use Acme\Auth\AccountType\Username;
use Phalcon\Di\ServiceProviderInterface;
class ServiceProvider implements ServiceProviderInterface
{
public function register(DiInterface $container)
{
$container->setShared(
'authManager',
function () {
$config = $this->get('config');
$manager = new Manager($config->path('auth.expiration'));
$manager->registerAccountType(Username::NAME, new Username());
return $manager;
}
);
}
}
Add account types
Different account types may be added by creating a class that implements Prest\Auth\AccountType
. This interface requires you to provide a login
and an authenticate
method.
For example Acme\Auth\AccountType\Username
class:
namespace Acme\Auth\AccountType;
use Phalcon\Di;
use Phalcon\Security;
use Prest\Auth\Manager;
use Acme\Model\UserModel;
use Prest\Auth\AccountType;
class Username implements AccountType
{
const NAME = 'username';
public function login($data)
{
/** @var \Phalcon\Security $security */
$security = Di::getDefault()->get(Services::SECURITY);
$username = $data[Manager::LOGIN_DATA_USERNAME];
$password = $data[Manager::LOGIN_DATA_PASSWORD];
/** @var User $user */
$user = User::findFirst([
'conditions' => 'username = :username:',
'bind' => ['username' => $username],
]);
if (!$user) {
return null;
}
if (!$security->checkHash($password, $user->password)) {
return null;
}
return (string)$user->id;
}
public function authenticate($id): bool
{
return User::count(['conditions' => 'id = :id:', 'bind' => ['id' => $id]]) > 0;
}
Middleware
The middleware can be instantiated as follows:
use Prest\Middleware\AuthenticationMiddleware;
$eventsManager->attach('micro', AuthenticationMiddleware::class);