🌮

ログインの基礎まとめた

2025/03/08に公開

目的
ログイン機能を理解するために、最初のステップとしてログインの基礎を学習する。

ログイン機能の仕組み

一般的に、ログインする際にユーザーを識別するための情報は
・メールアドレス(or ユーザー名など)
・パスワード

この組み合わせを使用し、データベースに登録されているリストからログインするユーザーを検索する。

ユーザーが見つかった場合、プログラムはそのユーザーの情報をセッションに保存し、それ以降の画面では「セッションにログイン情報があるかどうか」をチェックする。

引用:https://blog.senseshare.jp/login-mechanism.html

しかしセッションは、未操作状態で一定時間経つと自動的に破棄されるため、ログイン状態をずっと保持させておくことは出来ない。
そこで、次回以降自動的にログインさせる仕組みとして、ユーザーが操作するブラウザのCookieというデータの保存領域を活用する。

最初にログインした際、トークンを発行し、それをCookieとデータベースに保存する(トークンにはセキュリティのために有効期限も設定しておく)。
引用:https://blog.senseshare.jp/login-mechanism.html

次にユーザーがアクセスした時

  1. Cookieにトークンがあるかどうかをチェック。
  2. あればそのトークンをデータベースと照合。
  3. トークンが一致するユーザーデータが存在し、有効期間内であれば、そのユーザーで自動ログインさせる。
    (ユーザーによってログアウトが行われた際は、トークン情報も削除する。)

    引用:https://blog.senseshare.jp/login-mechanism.html

Laravelの認証・認可

Laravelにはログインを実現するためのパッケージが備わっており、Laravelの認証機能は素早く、安全な方法で実装が可能である。

認証と認可の違い

認証(Authentication):そのユーザが誰であるかを判断すること
認可(Authorization):そのユーザで何ができるかを判断すること

引用:https://qiita.com/mgmgmogumi/items/722567cd2f1421d7e11c

認証の仕組み

認証はミドルウェア(OSとアプリケーションの間に入って処理を行うもの)を使って実現しており、リクエスト・レスポンス時にフィルタリングを行ってくれる。
ログインの認証では、web・guest・authの3つのミドルウェアを使用している。

認証前

認証後

ミドルウェアの定義

app/Http/Kernel.phpでミドルウェアの定義をしている。
$middleware → 全ての処理に共通して処理を行うミドルウェアを定義。各ルートが呼ばれたときに実行される。
$middlewareGroups → 複数のミドルウェアをグループとして定義。
$routeMiddleware → 単体で使うミドルウェアをキーと共に定義。

認証・認可のカスタマイズ

Laravelでは、デフォルトでconfig/auth.phpに認証の設定がされている。
独自の認証のカスタマイズをしたい場合は、GuardProvierを設定し、認可のカスタマイズをしたい場合は、GatePolicyを設定する。
Guardは各リクエストのユーザー認証を定義し、Provierは永続ストレージ(MySQLなど)からのユーザーの取得方法を定義する。
認証パラメータはconfig/auth.phpファイルで定義し、認証の振る舞いを調整するオプションを設定することができる。
(カスタムGuardAuthServiceProvider.phpで定義する。)

ミドルウェアの使用

ミドルウェアの使用方法には主に二つのやり方がある。

  1. ルーターでミドルウェアを使用する。
  2. コントローラーでミドルウェアを使用する。
    (webのミドルウェアはroutes/web.phpのルートに対して使用されている。)
    使用例:routes/app.phpでカスタムGuardを使用など

Basic認証・Bearer認証

HTTP上で認証を行う場合

  • セッションによる認証
  • リクエストボディにトークンを含める認証
  • 独自ヘッダにトークンを含める認証
  • Authorizationヘッダーを用いた認証(Basic・Digest・Bearer・OAuth)
  • JWT認証など
    様々な方法がある。

Basic認証

ほぼすべてのWebサーバー・ブラウザ・ツールで実装されているため、簡単に導入することができる。
セキュリティ面にデメリットがあり、簡単にユーザ名、パスワードを盗まれてしまう
(採用されているBase64は暗号化ではないため)。
Basic認証方式を採用する場合、HTTPSを利用することが必須条件となる。
本来はWebサーバー内のディレクトリへのアクセスを管理するため技術のため、Single Sign Onのようなサービスを跨いだ認証はできない。
 (↑ example1.とexample2.のように同時認証ができない。)

動作の流れ

  1. ブラウザがRequestを送る
  2. サーバーがBasic認証が必要なことを伝える(WWW-Authenticateヘッダに「Basic」をセットした401 Authorization Requiredを返信)
  3. ユーザーがユーザー名とパスワードをブラウザに入力する
  4. ブラウザはユーザー名とパスワードを「:」でつなげてBase64でエンコードしてAuthorizationヘッダーにセットしてRequestを送る
  5. サーバーはユーザー名とパスワードをBase64でデコードして認証を行う
  6. 認証が成功すると、サーバーはRequestされたページを送る
  7. ブラウザは認証状態をキャシュし、キャッシュがクリアされるまでユーザーが再認証を要求されることはない
    動作5で認証に失敗した場合は、401(Unauthorized)、認可に失敗した場合は403(Forbidden)が手順6で送られる。
    (ブラウザが前提になっているが、Web APIの場合は事前に認証が必要なことを知っているので動作1〜3がなくなる)

Bearer認証

Bearer認証は, トークンを利用した認証・認可に使用されることを想定しており、HTTPでも使用しても良いとされている。
HTTPのAuthorizationヘッダにスキームとして指定でき、「 Authorization: Bearer <token> 」のように指定する。
トークンの形式はtoken68の形式で指定することが定められている
(1文字以上の半角英数字, - (ハイフン), . (ドット), _ (アンダーバー), ~ (チルダ), + (プラス), / (スラッシュ)から構成された文字列)

動作の流れ

  1. クライアントは、事前に入手したアクセストークンをtoken68形式でAuthorizationヘッダーにセットしてRequestを送る
  2. サーバーはアクセストークンが有効なものか確認する
  3. アクセストークンが有効だった場合、Webサーバはークライアントが要求したリソースを送る

動作2で認証が失敗した場合、サーバーは401(Unauthorized)を返信する(WWW-Authenticateヘッダ内のerrorパラメータに失敗した原因が記載されている)

・成功
WWW-Authenticate: Bearer realm=""
 
・リクエストにAuthorizationヘッダが含まれていない(401 Unauthorized)
WWW-Authenticate: Bearer realm="token_required"
 
・トークンが失効, 破損しているケース(401 Unauthorized)
WWW-Authenticate: Bearer error="invalid_token"
 
・トークンのスコープが不十分なケース(403 Forbidden)
WWW-Authenticate: Bearer error="insufficient_scope"

機密性の高いデータを扱うサービスでは、比較的安全なBearer認証、OAuth認証方式を目にすることが多い。

参考ページ:
ログインってどういう仕組み?:https://blog.senseshare.jp/login-mechanism.html
Laravelの認証機能を徹底解説:https://kinsta.com/jp/blog/laravel-authentication/
Laravelの認証の仕組み:https://qiita.com/mgmgmogumi/items/722567cd2f1421d7e11c
Laravel の Guard(認証) って実際何をやっているのじゃ?:https://qiita.com/tomoeine/items/40a966bf3801633cf90f
Bearer認証について:https://qiita.com/h_tyokinuhata/items/ab8e0337085997be04b1#bearer認証
Basic認証、Digest認証、Bearer認証、OAuth認証方式について:https://architecting.hateblo.jp/entry/2020/03/27/130535

Discussion