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」を指定する事ができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
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]) ?>
」となります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<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行目のようにログ出力を追記します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
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の動作の違い」
ログ出力をすると下記の様なログが出力されます。
1 2 3 4 5 6 7 8 9 10 |
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
」の方もログ出力をしてみるといいでしょう。
1 2 3 4 5 6 7 8 9 10 |
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は認証がなくてもアクセスができますので、新しいユーザの登録や、ユーザ情報を更新して、間違いないパスワードを生成するといいでしょう。
1 2 3 4 5 6 7 |
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の関連記事
CakePHP4系、5系でカラムを指定して値があるかないかのチェックするCakePHP4、5のnewEmptyEntityで作成したオブジェクトは空なのか、確認してみた
CakePHP4、5でSELECT telephone as tel FROM usersの様にasでカラムに別名を付ける方法
CakePHP4、5の認証処理で認証が通らない際の確認方法と確認箇所の紹介
CakePHP5系で認証機能のAuthenticationプラグインをインストール・エラー発生注意
CakePHP5でヘルパーから他のヘルパーを読み込む方法・CakePHP4からの変更点
CakePHP5系でDeprecatedを回避しfindListでキーと値のカラムを指定して取得する方法
その他の「CakePHP5」に関する記事一覧
GoogleAdwords
GoogleAdwords
この記事が参考になったと思いましたらソーシャルメディアで共有していただけると嬉しいです!
関連記事
-
CakePHP 2.3 Search Pluginで検索処理 その2表示件数を動的に変える方法
CakePHPの検索プラグイン Search Pluginの検索処理の中で動的に表示件数を変える方法です。
-
CakePHPで favicon.icoやapple-touch-icon-144-precomposed.pngが could not be foundのエラーが出るときの対処方法
CakePHPで「CakeDC/Users」などルーティングを行うプラグインを利用するときに、favicon.icoやapple-touch-icon-144-precomposed.pngがNotFoundエラーになることがある。その対処方法の解説。
-
CakePHP 2.3でファイルのアップロード処理を作る
CakePHPでプラグインを使わないファイルアップロード処理を解説します。簡単です。DBにファイルを格納する方法も。
-
CakePHP3にデイトピッカー jQuery UI DatePickerを実装する手順の解説
CakePHP3にjQuery UIのDatePickerを実装する手順を説明。併せて、デイトピッカーを設置に関連するCakePHP3の解説と、テーマを変更したり、表記を変更するカスタマイズする方法なども紹介。
-
CakePHP3ログファイルへの出力・$this->log()、独自ログへの出力方法の解説
コントロール、モデルの変数の中身を見るときはログに出力する方法が有効です。$this->log()を利用すると変数だけじゃなく、連想配列、オブジェクトも簡単にログ出力ができます。
-
CakePHP3のcontroller内でテンプレート、レイアウトを変更する際の指定方法
CakePHP3でテンプレートファイルやレイアウトファイルをデフォルトのものから別のものに変更したい場合の指定方法を解説。
-
CakePHP 2.3 Search Pluginで検索処理 その6ORDER、sortソートの機能
CakePHPの検索プラグイン Search Pluginの検索処理の中で order、ソートについての解説です。
-
CakePHP 2.3 ID以外のカラムでアソシエーション(連携)をさせる場合
ID以外のカラムでアソシエーション(連携)させるための考え方とサンプルソースを用いての説明を行っています。
-
CakePHP4のcake cache clear_allでPermission deniedはパーミッションの変更が必要
CakePHP4でキャッシュをクリアするコマンドcake cache clear_allでPermission deniedのエラーが出るのはcakeにパーミッションが足りないとき。その対処方法を解説。
-
CakePHP3のCakeDC/Usersのバリデーションのカスタマイズ方法解説
CakeDC謹製Usersプラグインの紹介。Usersのカスタマイズとして入力項目のバリデーションの変更を、プラグインのファイルは触らずオーバーライドにより実装する方法を解説する。