Rails 8で基本的な認証ジェネレータが導入される(翻訳)
DHHは最近、以下のAdd basic authentication generatorというタイトルのissueをRailsリポジトリに投稿しました。
今のRailsには、基本的な認証機能で必要となる主な材料はひととおり揃っているのに、それらをどう組み合わせたらよいかをまだよくわかっていない新規開発者が多いため、最終的にそうしたメカニズムを隠蔽するオールインワンのgemに頼っている。
#50446より
この問題に対処するため、Rails 8では基本的な認証をRailsアプリケーションに追加する作業をシンプルにできるジェネレータが導入されました。本記事では、この認証scaffoldに含まれるコンポーネントについて解説します。
🔗 Railsアプリケーションに認証を追加する。
Railsアプリケーションで、基本的な認証システムをセットアップするには、以下のコマンドを実行します。
bin/rails generate authentication
このコマンドは、認証を実装するときの基本となる重要なファイルセットを生成します(データベースでトラッキングされるセッションや、パスワードのリセット機能など)。生成されるscaffoldについてはgistをご覧ください。
このauthenticationジェネレータで作成されるコンポーネントを調べてみましょう。
🔗 モデルとマイグレーション
ユーザーアカウントやセッション管理の基盤を用意するため、以下の3つのモデルと、それらに対応するマイグレーションがセットアップされます。
セットアップには以下が含まれます。
- CreateUsersマイグレーション
- このマイグレーションは
users
テーブルを作成します。このテーブルにはuniqueインデックス付きのemail_address
フィールドと、パスワードをハッシュ化して安全に保管するためのpassword_digest
フィールドがあります。 - CreateSessionsマイグレーション
- このマイグレーションは、
sessions
テーブルを作成します。このテーブルには、一意のtoken
フィールドの他に、ユーザーのデバイスやネットワークの詳細情報を記録するためのip_address
フィールドとuser_agent
フィールドがあります。Session
モデルでは、has_secure_token
を用いて一意のセッショントークンを生成します。 Current
モデル- このモデルは、リクエスト単位でステートを管理し、委譲先の
user
にあるメソッドを介して現在のユーザーの情報へアクセス可能にします。 - bcrypt gemもGemfileに追加される
- このgemが存在しない場合は新規追加し、このgemがコメントアウトされている場合は、コメントアウトを解除してgemを有効にします。続いて、
bundle install
を実行してgemをインストールします。
🔗 認証のconcern
認証ロジックやセッション管理のコア部分は、Authentication
concernにカプセル化されています。
require_authentication
- これは
before_action
用コールバックであり、resume_session
メソッドを用いて既存のセッションの復元を試みます。セッションが見つからない場合は、request_authentication
メソッドを用いてユーザーをログインページにリダイレクトします。 resume_session
find_session_by_cookie
メソッドでcookieから取得した署名済みトークンを用いてセッションを復元します。セッションを現在のセッションとして設定してから、set_current_session
メソッドを用いてトークンを永続的なHttpOnly
cookieに保存します。authenticated?
- 現在のユーザーにアクティブなセッションがあるかどうかをチェックするヘルパーメソッドです。
allow_unauthenticated_access
- このクラスメソッドは、
require_authentication
コールバックで特定のアクションをバイパスするのに用います。 after_authentication_url
- 認証後のリダイレクト先URLを返します。
start_new_session_for(user)
- 指定のユーザーのデバイスやIPアドレスの詳細情報を渡して新しいセッションを作成し、現在のセッションを設定します。
terminate_session
- 現在のセッションを破棄して、cookieからセッショントークンを削除します。
🔗 セッションを管理する
SessionsController
はユーザーのセッション管理を処理するコントローラで、以下のアクションがあります。
new
- ユーザーがログイン情報を入力するログインフォームを表示します。
new.html.erbビューテンプレートファイルには、email
フィールドとpassword
フィールド、flashメッセージによる成功またはエラー表示機能、パスワード回復用リンクが含まれています。 create
- ユーザーが入力したログイン情報でユーザーを認証します。
新規セッションを作成してからafter_authentication_url
にリダイレクトします。認証に失敗した場合は、ログインフォームにリダイレクトしてエラーメッセージを表示します。 destroy
- ユーザーのセッションを破棄してログインフォームにリダイレクトします。
以上を組み合わせた基本的な認証フローは、以下のような感じになります。
🔗 パスワードリセット機能
基本的なパスワードリセット機能には、「パスワードリセットのリクエスト開始」「メールによるリセット手順の送信」「パスワードの更新」が含まれます。PasswordsController
は、これらを以下のアクションで管理します。
new
- パスワードリセットのリクエスト送信用フォームを、new.html.erbビューテンプレートを用いて表示します。
create
- パスワードリセットのリクエストを処理します。
ユーザーが存在する場合はPasswordMailer
でリセット用メールを送信し、メッセージを表示してリダイレクトします。
送信されるメールにはパスワードリセットページへのリンクが含まれており、リンクにはpassword_reset_token
パラメータがあります。このpassword_reset_token
は、#52483でhas_secure_password
に新しく追加されたコンフィグの一部です。トークンが失効するまでの期間はデフォルトで15分です。 edit
- 新しいパスワードを設定する画面をedit.html.erbビューテンプレートを用いて表示します。
update
- ユーザーのパスワードを更新します。
更新に成功した場合はリダイレクトし、失敗した場合はアラートを表示します。 set_user_by_token
- これは
edit
アクションやupdate
アクションのbefore_action
コールバックです。リクエストのパラメータに含まれるpassword_reset_token
を元に適切なユーザーの識別情報を取得します。
以上をまとめると、パスワードリセットのフローは以下のようになります。
🔗 現在の制限と考慮点
現在のauthenticationジェネレータは、メールアドレスとパスワードによる既存ユーザーのログインをサポートしていますが、新規アカウントの作成は行いません。今後のアップデートでユーザーアカウント作成機能やその他のカスタマイズが組み込まれる可能性もあります。
詳しくは以下のプルリクをご覧ください。
- Add basic sessions generator by dhh · Pull Request #52328 · rails/rails
- Add password reset to authentication generator by dhh · Pull Request #52472 · rails/rails
- Add a default password reset token to has_secure_password by dhh · Pull Request #52483 · rails/rails
概要
元サイトの許諾を得て翻訳・公開いたします。
なお、本記事で取り上げられているのはいわゆるHTTP BASIC認証↓とは異なりますのでご注意ください。
参考: 11.1 HTTP BASIC認証 -- Action Controller の概要 - Railsガイド