AuthenticationMiddleware の挙動が把握できておらず、ハマったのでメモ
AuthenticationMiddleware の挙動
チュートリアル に
// src/Application.php
public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
$middlewareQueue
// 〜
->add(new AuthenticationMiddleware($this));
// 〜
}
public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
{
// 〜
$authenticationService->loadAuthenticator('Authentication.Session');
$authenticationService->loadAuthenticator('Authentication.Form', [
// 〜
]);
// 〜
}
// UsersController
public function login()
{
// 〜 略 〜
$result = $this->Authentication->getResult();
// 〜 略 〜
}
このようなサンプルがあるが、getResult() までの流れはこのようになっている
getResult()の Result はミドルウェアの段階でセットされるAuthenticationMiddlewareでSessionAuthenticator->FormAuthenticatorの順で認証して、認証できた時点で Result が Success になる- ログイン中は
FormAuthenticatorは実行されない (username + password による認証は行われない)
今回やりたかった事
- ログイン中であっても username + password による再認証を行いたい
実現方法
- login アクション内 で
FormAuthenticatorを取得してusername + passwordによる認証を行う
サンプル
public function login()
{
/** @var AuthenticationComponent $authenticationComponent */
$authenticationComponent = $this->Authentication;
// 既存のセッションを削除
$authenticationComponent->logout();
/** @var AuthenticationService $authenticationService */
$authenticationService = $authenticationComponent->getAuthenticationService();
$authenticators = $authenticationService->authenticators();
// FormAuthenticator を取得
$formAuthenticator = null;
foreach ($authenticators as $authenticator) {
if ($authenticator instanceof FormAuthenticator) {
$formAuthenticator = $authenticator;
}
}
if (is_null($formAuthenticator)) {
throw new \Exception();
}
// FormAuthenticator で username + password による認証を行い、セッションを生成
/** @var FormAuthenticator $formAuthenticator */
$authenticate = $formAuthenticator->authenticate($this->_request());
if (!$authenticate->isValid()) {
// 適宜
}
$authenticationComponent->setIdentity($authenticate->getData());
// 〜
}