CakePHP4、5の認証処理で認証が通らない際の確認方法と確認箇所の紹介
2025/01/31
CakePHP4、5の認証処理で認証が通らない際の確認方法と確認箇所の紹介
CakePHP4、5の認証処理で「Invalid email or password」が解消しない!
CakePHP4、CakePHP5などではシンプルな認証として、標準的な認証処理がプラグインとして提供されています。
その認証処理を使用している処理が
「何度 ID、PASSを入力しても『Invalid email or password』というメッセージが出て認証が通らない!」
という場合の確認ポイントを紹介します。
「Invalid email or password」が解消しない不具合の発生の経緯
「Aシステム」という既存の稼働中のシステムがありました。
それに対して、関連システムとして「Bシステム」の開発が始まりました。
「Bシステム」の一部の機能は「Aシステム」の APIを経由して情報を取得する処理がありましたので、「Bシステム」の開発と並行して、「Aシステム」の改修も行っていました。
また、いずれも CakePHPと同じ認証処理を使用して作られていましたが、「Aシステム」は「ID+PASS」でログイン認証を行い、「Bシステム」は「E-Mail+PASS」でログイン認証する仕組みでした。
それらのシステムは、私の PCの画面上で同時並行して開発を行っていました。
そして、悲劇が起こるのです。
「Bシステム」のログイン処理を作っているつもりが
「Aシステム」のログイン処理を修正してしまっていた!
のです。
というワケで、
/src/Application.php
に追加する下記の処理の「id」の部分を、知らず知らずのうちに「email」に書き換えてしまっていたのですが、それを調査して不具合点を発見する手続きを紹介します。
まぁ、こんなところではまる方はほとんどいないと思いますが、ほとんどいないため、どうやって確認するかがの記事がなく、途方に暮れてしまいましたので、一人の方でも参考になる方があれば、と思って記事を書きました。
ログイン認証の usernameを指定する Application.phpについて
まず初めに、今回の不具合の原因となった個所は、
/src/Application.php
の下記の 12行目、22行目の「'username' => 'id',」の箇所です。
ここは、認証対象となる「username」と「password」になる項目を指定する項目です。
「username」に「id」を指定すると「ID+PASS」、「email」を指定すると「E-Mail+PASS」で認証するように、ログイン認証する「username」を指定する事ができます。
public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
{
$authenticationService = new AuthenticationService([
'unauthenticatedRedirect' => '/users/login',
'queryParam' => 'redirect',
]);
// 識別子をロードして、電子メールとパスワードのフィールドを確認します
$authenticationService->loadIdentifier('Authentication.Password', [
'fields' => [
'username' => 'id',
'password' => 'password',
]
]);
// 認証子をロードするには、最初にセッションを実行する必要があります
$authenticationService->loadAuthenticator('Authentication.Session');
// メールとパスワードを選択するためのフォームデータチェックの設定
$authenticationService->loadAuthenticator('Authentication.Form', [
'fields' => [
'username' => 'id',
'password' => 'password',
],
'loginUrl' => '/users/login',
]);
return $authenticationService;
}
上記のソースコードは、下記の Cookbookに記載があるソースとほぼ同じですが、まさに「username」を指定する箇所を、「email」から「id」に変更しています。
https://book.cakephp.org/5/ja/tutorials-and-examples/blog-auth-example/auth.html#id5
ログイン認証の usernameを指定するログイン画面の login.phpについて
また、「username」の項目を変更する際に変更する箇所は下記のログイン画面の項目となります。
/templates/Users/login.php
対象となるファイルは上記のファイルで、変更箇所は 7行目の「= $this->Form->control('id', ['required' => true]) ?>」となります。
<div class="users form">
<?= $this->Flash->render() ?>
<h3>Login</h3>
<?= $this->Form->create() ?>
<fieldset>
<legend><?= __('ユーザー名とパスワードを入力してください') ?></legend>
<?= $this->Form->control('id', ['required' => true]) ?>
<?= $this->Form->control('password', ['required' => true]) ?>
</fieldset>
<?= $this->Form->submit(__('Login')); ?>
<?= $this->Form->end() ?>
<?= $this->Html->link("Add User", ['action' => 'add']) ?>
</div>
Cookbookでは「email」となっている記述を「id」に変更しています。
CakePHP4、5の認証処理を実装するにあたって、変更する箇所があるとすればこれらの箇所くらいかと思います。
(場合によっては、認証対象のテーブルを「Users」ではないテーブルを対象にする場合は、「Users」の箇所を変更することもあるかもしれませんね。)
ログイン認証で「Invalid email or password」が解消しない場合はログ出力をする
認証処理は実装したけどログインできない、もしくは、私のように先日までは認証処理が動いていたので、何かのメンテナンスをしたことをきっかけに認証が通らなくなった、という場合は、下記の通りログ出力をしてみてください。
/src/Controller/UsersController.php
対象ファイルは上記で、6行目のようにログ出力を追記します。
public function login()
{
$this->request->allowMethod(['get', 'post']);
$result = $this->Authentication->getResult();
$this->log(var_export($result,true), "error", ['scope' => ['queriesLog']]);
// $this->log(var_export($result,true), "error");
// POSTやGETに関係なく、ユーザーがログインしていればリダイレクトします
if ($result->isValid()) {
// ログイン成功後に /article にリダイレクトします
$redirect = $this->request->getQuery('redirect', [
'controller' => 'Users',
'action' => 'menu',
]);
return $this->redirect($redirect);
}
// ユーザーの送信と認証に失敗した場合にエラーを表示します
if ($this->request->is('post') && !$result->isValid()) {
$this->Flash->error(__('Invalid email or password'));
}
}
上記の 6行目は「ログスコープ」という機能を利用して、ログファイル「/log/queries.log」に出力するように指定しています。
コメントアウトしていますが、7行目の記述を有効にすると、ログは「/log/error.log」に出力されます。
詳しくは下記の記事を参考にしてください。
「CakePHP4でロギングスコープやログレベルを使用してログを出し分ける方法を解説」
また、CakePHP4系、5系では配列をログ出力をする際は「var_export()」が必要になりました。あわせて上記の記事を参考にしてください。
また、「var_export()」が何者か、については下記の記事を参考にしてください。
「PHPのデバッグで使う print_r、var_dump、var_exportの動作の違い」
ログ出力をすると下記の様なログが出力されます。
2025-01-01 00:00:00 error: Authentication\Authenticator\Result::__set_state(array(
'_status' => 'FAILURE_IDENTITY_NOT_FOUND',
'_data' => NULL,
'_errors' =>
array (
'Password' =>
array (
),
),
))
2行目の「_status」に、認証が認められなかった原因が出力されていますので、これを参考にします。
上記の例では「FAILURE_IDENTITY_NOT_FOUND」となっていますので、単純に、ID、PASSが合っていないのかと思います。
ResultInterface::SUCCESS:成功した場合
ResultInterface::FAILURE_IDENTITY_NOT_FOUND:IDが見つからなかった場合
ResultInterface::FAILURE_CREDENTIALS_INVALID:資格情報が無効な場合
ResultInterface::FAILURE_CREDENTIALS_MISSING:リクエストに認証情報がない場合
ResultInterface::FAILURE_OTHER:その他の種類の失敗
認証のステータスについては下記の記事が参考になります。(CakePHP3系以降の Cookbookには記載がないようです。)
CakePHP2 Cookbook 認証コンポーネント
https://www.m-kobayashi.org/CakePHP/Documents/Plugin/Authentication/authentication-component.html#
また、この記事を書くきっかけになった「Application.php」の「username」が間違っている場合は、「FAILURE_CREDENTIALS_MISSING」となりました。
ログイン画面で入力している「username(ID)」と認証に使用する「username(email)」が違うため、「POSTした値に認証情報が含まれていないよ」というエラーになった、ということです。
このように、ログインのステータスをログ出力することで、なぜエラーになっているのか、少しは情報が増えるかと思います。
ちなみに、今回さらに混乱をした原因として、入力しているパスワード「test」はコピペした値を入力していました。
が、「test」は「test」だけではなく「(タブ)test」という状態のものをコピーしていて、正しい「test」だけではなかったため、先の「FAILURE_CREDENTIALS_MISSING」の不具合が解消しても、「FAILURE_IDENTITY_NOT_FOUND」のエラーが解消しないという、二重の不具合でより解消に時間がかかるというものでした。
「FAILURE_IDENTITY_NOT_FOUND」のエラーが出るときは、入力値を確認するために、下記の 6行目のように、入力情報である「$this->request」の方もログ出力をしてみるといいでしょう。
public function login()
{
$this->request->allowMethod(['get', 'post']);
$result = $this->Authentication->getResult();
$this->log(var_export($this->request), "error", ['scope' => ['queriesLog']]);
$this->log(var_export($result,true), "error", ['scope' => ['queriesLog']]);
:
:
略
この時、ログ出力に「var_export()」を使用することで、「test」の前に何か入っている、と気づくきっかけになるのではないかと思います。
(この点は「print_r()」より優れている点かと思います。)
というワケで、CakePHPの認証処理もエラーが発生して想定の動作をしない場合は、ログ出力をして、エラーメッセージを読むことで少しずつ原因に近づいていく対処が必要ということになりますね。
非常にレアな状況に対応するための記事かと思いますが、どなたかのお役に立てば、と思います。
ログイン認証を必要としない Action(ページ)を指定する方法
また、ユーザ認証処理によって、ログイン認証できないため、ユーザ情報の登録も更新もできなくて困っている、という場合は、下記の
/src/Controller/UsersController.php
の最初の方に記述しているであろう下記の認証が通っていなくてもアクセスできる Actionを指定する箇所に追記します。
認証処理を設置する Cookbookの記事にも記載がありますが、忘れている場合もあるかと思いますので、改めて記載しておきます。
具体的には、6行目の「['login']」となっている箇所を「['login',"add","edit"]」のように、Action名を追加します。
追加された Actionは認証がなくてもアクセスができますので、新しいユーザの登録や、ユーザ情報を更新して、間違いないパスワードを生成するといいでしょう。
public function beforeFilter(\Cake\Event\EventInterface $event)
{
parent::beforeFilter($event);
// ログインアクションを認証を必要としないように設定することで、
// 無限リダイレクトループの問題を防ぐことができます
$this->Authentication->addUnauthenticatedActions(['login']);
}
CakePHP4系、5系の認証に関する参考記事
最後に、CakePHP4系、5系で提供されている認証処理についての公式 Cookbookの記事の紹介です。
CakePHP5 Cookbook シンプルな認証と認可のアプリケーション
https://book.cakephp.org/5/ja/tutorials-and-examples/blog-auth-example/auth.html
CakePHP5 Cookbook CMS チュートリアル – 認証
https://book.cakephp.org/5/ja/tutorials-and-examples/cms/authentication.html
CakePHP4 Cookbook シンプルな認証と認可のアプリケーション
https://book.cakephp.org/4/ja/tutorials-and-examples/blog-auth-example/auth.html
CakePHP4 Cookbook CMS チュートリアル – 認証
https://book.cakephp.org/4/ja/tutorials-and-examples/cms/authentication.html
上記は、CakePHP4と 5の認証処理の紹介ですが、読んでもらえば分かる通り、4系と 5系の認証処理はほとんど同じです。
「CakePHP5系で認証機能のAuthenticationプラグインをインストール・エラー発生注意」
ですが、上記で記事にしていますが、使用するプラグイン「cakephp/authentication」は、4系では Ver.2、5系では Ver.3となっていますので、その点の注意は必要です。(公式 Cookbookが間違えていますので注意が必要です。)
その他の関連記事としては下記の記事でしょうか。
CakePHP4 Cookbook AuthComponent
https://book.cakephp.org/4/ja/controllers/components/authentication.html
CakePHP3系の認証処理も似たような認証処理として提供されていますが、CakePHP4になる時に少し変わりましたよ、という案内です。
これから CakePHP3系で新しいシステムの開発をすることは少ないかと思いますが、CakePHP3系から 5系へのシステム移行の際などには違いがあることを認識しておく方がよさそうです。
CakePHPの上記の認証処理はシンプルな造りで、追加する項目も、各システムに合わせて変更する箇所も少ないため、ほとんどの場合は迷うことなく実装することができるでしょう。
ですが、シンプルな造りであるからこそ、上手くいかなかったときは悩みが深まるのではないかとも思います。
CakePHP5の関連記事
CakePHPのpostlinkで生成した削除リンクをクリックしても処理が実行されない対処法CakePHP4、5のユーザ認証でID、PASS以外の削除フラグなども条件加える方法
CakePHP4、CakePHP5系の認証処理でログインの有無の確認、ユーザ情報の取得の方法
CakePHP4、5で$_SERVERと同じようにURIを取得する「getUri()」の紹介
getParam('action')で取得するアクション名は別関数に移動しても不変CakePHP4系、CakePHP5系のexists()でカラムを指定して値の有無をチェックする方法解説
CakePHP4、5のnewEmptyEntityで作成したオブジェクトは空なのか、確認してみた
CakePHP4、5でSELECT telephone as tel FROM usersの様にasでカラムに別名を付ける方法
CakePHP4、5の認証処理で認証が通らない際の確認方法と確認箇所の紹介
CakePHP5系で認証機能のAuthenticationプラグインをインストール・エラー発生注意
その他の「CakePHP5」に関する記事一覧
この記事が参考になったと思いましたらソーシャルメディアで共有していただけると嬉しいです!
関連記事
-
-
CakePHP3で Ajaxを使う方法の解説。3.6以降対応。Successとthenの両方を解説。
CakePHP3でajaxを利用する処理の実装方法を解説。プルダウンを変更するとデータベースの値を取得し検索結果の内容を変更するというような処理を想定。CakePHP3.6以降の CSRF対策対応済。
-
-
CakePHP3でアソシエーション先のカラムでデータをソートして取得したい
アソシエーション先のテーブルのカラムをキーにソートをしたデータを取得したい!ときの記述方法を解説。「orderAsc()」ではなく「contain()」の中にSort条件を記述する。
-
-
CakePHP4で現在処理しているコントローラー名、アクション名を取得する方法
CakePHP3で現在処理しているコントローラー名、アクション名を取得する方法を解説。複数の方法があるが、getParam()メソッドを使う方法が汎用性があって便利かも。
-
-
CakePHP4のCakeDC/Usersのログイン時のリダイレクトとユーザ権限管理の設定解説
CakeDC謹製UsersプラグインのCakePHP4版の紹介。ログイン認証後にリダイレクトする先の設定方法についての解説と実運用するために必要なコツを解説。便利な仕組みも仕様の理解があって初めてうまく使いこなせる。
-
-
CakePHP3で静的ページの作成は webrootか pagesを使う。トップページを参考に解説
CakePHP3で静的なページを設置する場合の方法(webrootとpagesとを活用する方法)を解説。pagesの解説はデフォルトのトップページがどう表示されているかを参考に解説。ルーティングの機能も。
-
-
CakePHP4の定数定義ファイルを環境変数によって本番と開発を振り分ける方法解説
CakePHP4で開発環境と本番環境とで違う設定ファイルを読み込ませて環境ごとに定数を切り替える方法を解説。Apacheのhttpd.confに環境変数を設定しそれを読み込み判別する。
-
-
CakePHP3のユーザ管理・ログイン認証プラグインCakeDC/Usersのインストール解説・3.6以降対応
CakePHP3のユーザ管理プラグイン Usersは、ユーザ登録、メール認証、ログイン認証、ユーザ管理、権限管理、reCAPTCHAなど会員制のサイトを簡単に実現可能。その導入方法、カスタマイズ方法を解説。
-
-
CakePHP3でCookieを保存、呼び出し、削除の操作・CakePHP3.7対応
CakePHP3.7でCookieを保存、取り出し、削除する方法を解説。CakePHP3でのCookieの取り扱いはバージョンごとに変更されるため、環境に合わせた方法を探す必要がある。
-
-
CakePHP 2.3で確認画面付きのお問い合わせフォームの作り方
CakePHPで確認画面付きのお問い合わせフォーム、メールフォームの作り方をサンプルを提示しながら解説。
-
-
CakePHP3でパンくずの指定は HTMLヘルパーを使って指定する方法を解説
CakePHP3でパンくずの指定方法の解説。2つのヘルパーがあるが簡単なHTMLヘルパーを使った方法を、実際の状況に合わせて3つのパターン(エレメント化、ブロック化)にして解説。