デザインでブランディングのお手伝い
デザインでブランディングのお手伝い
2019.07.31
#53
バックエンドへの道

Laravelの認証について調べてみた

エリカ

こんにちは、ディレクターのエリカです。Laravelで作成してもらったアプリケーションを利用しているときに、ログインまわりで気になった点があったので、Laravel標準の認証について少し調べてみました。

ログインは何分間維持される?

ログイン(認証)機能があるWebサービスを利用しているとよくあるのですが、何かの拍子にログイン画面に戻されてしまう場合があります。

この原因のひとつが、「ログイン保持期間の経過」なのですが、これはLaravelのログインも同様です。

Laravelではユーザーのログイン情報は有効期限とともに保持されます。そして、このログイン済みのユーザーからのアクセスの間隔が有効期限を超過していた場合は、そのログイン情報が破棄され、再度のログインを要求することになっているのです。

それでは、Laravelのログイン保持期間はどれくらいなのでしょうか。

.env ファイルの SESSION_LIFETIME がその期限になります。(ちなみにこの値は秒ではなく分なので、初期値では、120となっているので2時間になっていると思われます。)

SESSION_LIFETIME=120

つまり、ログインしてから120分後に再度アクセスすると、ログイン情報が破棄され、再度のログインが必要になります。

この値は変更することができますので、任意の期間を設定することができます。

Remember Meは何をやってる?

この定期的にログインさせなおすという機能はセキュリティー上の観点から有用ではあるというものの、ログインを度々要求するのは、対象ユーザーやインターフェースの都合上、なかなか難しい場合があるかもしれません。そこで、一度ログインしてしまえば、意図的にログアウトしない限り再度のログインを要求しないようにできる機能があります。

よく「ログイン情報を保持する」とか「ログインし続けたままにする」とか、そういったチェックボックスが配置されているログイン画面をみたことがあるかと思いますが、それがLaravelでは、「Remember Me」として用意されています。

これを利用すると、どういう処理が行われるのでしょうか。

この「Remember Me」を有効にしてログインした場合、前述のログイン保持期間を超えた場合でも、ログイン画面に戻らずログイン状態のまま操作を継続することができます。

ちなみに、これはどれくらいの期間有効なのでしょうか?

クッキーに必要な情報が書き込まれているのですが、そのクッキーの有効期限が5年になっていました。ただ、この期限のコントロールについては、設定値を変更すれば簡単に設定できる、というものではなく、ある程度コードを書く必要がありそうでした。

なお、この機能は「実際にログイン保持期間がそのものが延長される」というものではなく、本来であれば、前述のログイン保持期間の制限により、再度のログインが要求されるところを、ログイン画面が表示される前に、この機能が自動的に再度のログインを行います。

これにより、あたかもログインし続けているかのように見えますが、実際は新しいログインをしていることになるのです。

そして、このことは後述する419エラーに影響があります。もしかしたら、たまに見たことがあるかもしれません。このようなエラー画面です。

419エラーが発生するのはどういうとき?

LaravelのCSRF対策により、リクエスト時にトークンが送信されてきた場合に、セッションに書き込まれているトークンと一致するかを検証し、不一致であれば419レスポンス(前前掲のエラー画面)を返すようになっています。

このセッションに書き込まれているトークンは、いくつかのタイミングで変更されます。そのうちのひとつがログイン時になります。

つまり、CSRF対策が利用されているフォームなどにおいては、入力してから送信するまでの間に、ログインの保持期間が経過する、もしくは前述のRemember Me機能によるログインの継続が行われた場合は、既にトークンが変更されてしまっていますので、不一致による419エラーが発生してしまいます。

したがって、入力項目が多いフォームをWebサービスを開発する場合などは、フォームを細かく分割する、非同期で保存する、または、セッションの保持期間を長く設定するなどで、せっかくの入力内容が破棄されないように留意しておくことが必要です。

ログイン試行制限ってある?

無限試行によるログイン突破という攻撃にもある程対応できるように、ログイン試行回数が制限されています。

詳細は明記しませんが、ログインに失敗したときに、特定の情報をキーにしてその回数をカウントしていきます。この回数が閾値を超えた場合は、たとえログインのリクエストがあったとしても試行をせずに、ログイン失敗として処理してくれます。

これは、閾値および、その保持期間を任意で指定することができます。

ThrottlesLogins トレイトを利用しているクラスで、下記のプロパティを設定できます。標準では、Http\Controllers\Auth\LoginController になるかと思います。

$maxAttempts // 試行回数の閾値 (初期値 : 5)
$decayMinutes // 何分ロックするか(初期値 : 1)

まとめ

標準の認証でも十分洗練されていてよくできていますね。さらに、それぞれの機能を綺麗に拡張、または置き換えできるように設計されているので、いろいろな認証に対応可能です。

本当にすばらしいですね。