Auth0でRuby on Railsの認証を効率化する:初心者向け実践ガイド
Ruby開発者にとって、認証の選択肢は nowadays 非常に豊富になりました。自作のソリューションからプラグアンドプレイ型の認証まで、さまざまな方法があります。しかしご存知のとおり、独自の認証機構をゼロから構築するのはコストが高く、セキュリティ上のリスクも伴います。多くのチームにとって事実上の標準となっているのはDeviseですが、それに代わる選択肢が開発者の負担を大きく軽減してくれるかもしれません。
本記事では、Ruby on RailsアプリケーションにおけるAuth0のセットアップと活用方法を解説します。ロール(役割)の管理から、複数の認証プロバイダーによるユーザー認証まで、正しく始めるために必要な情報をすべて網羅しています。
はじめに
作業を始めるために必要なものは以下の2つです。
- Auth0アカウント
- Ruby on Railsアプリケーション(バージョン7.x以降)
Auth0はサードパーティ製の認証サービスで、無料プランでは最大7,000ユーザーまで対応できます。スタートには十分な規模であり、より高度な機能が必要になった場合でも料金設定は妥当です。
Auth0でのRailsアプリケーション設定
アプリケーションはリダイレクトやAPI呼び出しを通じてAuth0にユーザー認証を委ねるため、設定を安全に行う必要があります。
まずAuth0アカウント内で、テナント(tenant)の中にアプリケーションを作成しましょう。1つのアカウントで複数のテナントを作成でき、以下のような用途の分離に役立ちます。
- ドメイン名の分離
- 環境ごとの分離(開発環境、本番環境など)
- データを保存する国・地域の分離
最初のテナントを作成したら、次にアプリケーションを作成します。ここから作業を始めましょう。
アプリケーションパネルの「Settings」タブを開き、以下の情報をコピーして安全な場所に保存してください。
- ドメイン名:
app-name.[eu,us,..].auth0.com - クライアントID(Client ID)
- クライアントシークレット(Client Secret)
さらに、以下のApplication URIsも入力が必要です。ここではローカル開発環境用の値を設定します。
- Allowed Callback URLs:
https://localhost:3000/auth/auth0/callback(認証後にAuth0がリダイレクトするURL) - Allowed Logout URLs:
https://localhost:3000(ログアウト後にAuth0がリダイレクトするURL)
それでは、アプリケーションの設定に進みましょう。
Ruby on Railsアプリケーションの準備
rails newコマンドを使えば、素の状態のRuby on Railsアプリケーションを作成できます。
ここでは、データベースにSQLite3、CSSフレームワークにTailwindを使用するアプリケーションを生成します。minitestのインストールはスキップし、アプリケーション名は「Auth0 article」とします。
続いて、必要な属性だけを持つシンプルなUserモデルを生成します。
これで、アプリケーションの土台としてシンプルかつ実用的な構成が整いました。
Auth0 Gemの追加
Ruby on RailsアプリケーションでAuth0を利用するには、omniauth-auth0とomniauth-rails_csrf_protectionというGemが必要です。
Auth0の設定
開発環境の認証情報を保存するために、小さな設定ファイル(config/auth0.yml)を作成します。
ERBを使えば、環境変数を参照することも可能です。
もちろん、Railsの暗号化認証情報(credentials)を利用すれば、より最新のベストプラクティスに沿った運用ができます。
このファイルは、これから作成するAuth0イニシャライザ(config/initializers/auth0.rb)で使用されます。
ご覧のとおり、Rails.application.config_forを使ってYAMLファイルの内容を便利なハッシュとして読み込んでいます。これはRailsの暗号化認証情報ストレージを含む、任意のシークレット管理ライブラリに置き換えることもできます。
以下のポイントに注目してください。
- プロバイダー名(
:auth0) - YAMLファイルから読み込んだ3つの項目。
AUTH0_CONFIGハッシュ経由で使用される callback_pathキーとその値。Auth0の管理画面で設定したものと一致させるauthorize_paramsと、その中のscopeキー。詳細は後述します
次に、認証を可能にするためのインターフェースとルーティングを作成していきます。
Tailwindを使ったルートとUIの構築
この例では、TailwindCSSを使用したRuby on Rails 7.1のアプリケーションを扱います。
以下のコマンドを実行してください。
次に、indexアクションを持つ2つのコントローラーを追加し、認証フローのテスト準備を整えます。
これら2つのコマンドにより、以下が生成されます。
- indexアクションを備えた
public_controller.rbとprivate_controller.rb - 対応するルート定義
- 対応するビューファイル
続いて、コールバックとエラーを処理するAuth0コントローラーを追加します。コントローラーファイル(bin/rails g controller auth0)を作成し、以下のコードを記述してください。
そして、これら3つのアクションを使うようにルートを更新します。
最後に、publicビューとprivateビューにそれぞれLoginボタンとLogoutボタンを配置します。
これで「https://localhost:3000」にアクセスできます。Loginボタンをクリックするとprivateページへリダイレクトされ、そこにLogoutボタンが表示されているはずです。
ただし、まだ足りない要素がいくつかあります。
- ユーザープロフィールからのデータ取得
- ユーザーの識別と認可(authorization)の処理
スコープとデータの操作
少し立ち戻って、イニシャライザ(config/initializers/auth0.rb)をもう一度見てみましょう。
ここで重要なのはscopeの指定、すなわちopenid profileです。これはAuth0に対して「以下の情報に関心がある」ことを伝えています。
- プロバイダー名(Auth0)
uid:ユーザーを一意に識別する識別子infoハッシュ:名前、プロフィール画像のURL、空の'email'キーを含むextra_infoハッシュ:名前とプロフィール画像に加え、姓・名のペアも含む
スコープについて詳しくは、Auth0公式ドキュメントを参照してください。
上記の情報は非常に価値があり、少なくとも初回ログイン時には、そのデータをアプリケーション内のテーブルに保存しておくべきです。
そのためには、auth0_controller内、具体的にはcallbackアクションでリクエスト・レスポンスの内容を利用します。
リダイレクトの直前にブレークポイントを設置し、ハッシュの中身を確認しながら試してみると良いでしょう。
通常はメールアドレスも取得したいはずです。その場合は、scopeを次のように更新します。
アプリケーションサーバーを再起動してログイン手順をやり直すと、追加情報へのアクセス許可を求められます。
これで、callbackアクション内で次のような処理が書けるようになります。
これにより、ユーザーのローカルプロフィールを常に最新の状態に保てます。
セッションについて
セッションとは、Ruby on Railsアプリケーションにおける特別なハッシュです。コントローラーとビューからアクセスできる限定的なストレージであり、訪問者ごとに一意です。
セッションは「開く」「閉じる」が可能です。特定のデータセットが必要な場合にセッションをオープンと判断し、データが存在しなければクローズしているとみなせます。
Auth0コントローラー内の以下の行を思い出してください。
1行目はハッシュのraw_infoキーの値をセッションハッシュに書き込み、2行目はセッションハッシュをクリアしています。
そして、ApplicationHelperに次のようなヘルパーメソッドを定義できます。
セキュリティ上の考慮点
次に、これをコントローラー用のconcernとして活用しましょう。考え方としては、「ログイン済みユーザーのみアクセスできるコントローラー」を定義することです。たとえばprivate_controllerが該当します。
以下のようなconcernファイルを書きます。
あとは、コントローラー内で次のように使用するだけです。
未ログインの訪問者が/private/indexページを開こうとすると、自動的にサイトのルートへリダイレクトされます。
他プロバイダーとの連携
Auth0経由なら、複数の認証プロバイダーを利用できます。ただし、デフォルトで設定されているのはGoogleです。多くの企業にとってはこれで十分でしょう。
追加のプロバイダーが必要な場合は、Auth0ダッシュボードで対象テナントの「Authentication」メニューを開き、「Social」サブメニューから追加のプロバイダーを設定できます。
また、Auth0では多要素認証(MFA)の設定も可能です。
これらの設定手順以外は、プロセスは変わりません。アプリケーション側は、訪問者が認証済みであることを示すデータを受け取るだけです。
認可への第一歩
これでユーザーを認証し、コールバックを通じてその情報をアプリケーションに渡せるようになりました。ハッシュからユーザーのメールアドレスを取り出し、データベース内の該当ユーザーを見つける方法もすでに確認しました。
ここから先は、認可ポリシーを定義する段階です。
Punditは認可ポリシーを定義・活用するための優れた選択肢ですが、ユーザーのロール(役割)のチェックに依存します。
role属性を使うのが、実際には最も簡単な方法です。Railsコンソールやアプリケーションの管理画面でユーザーを作成する際に、初回ログイン前に値を設定しておきましょう。
あるいは、管理者のメールアドレス一覧を用意し、ユーザー作成時にそのメールアドレスと照合する方法もあります。
以上で完了です!
まとめ
本記事では、以下をセットアップしました。
- Auth0上のテナントとアプリケーション
- Ruby on RailsアプリケーションへのAuth0関連Gemの導入
- アプリケーション内のルートとビュー
さらに、以下の内容も扱いました。
- セッションの概念の確認と活用方法
- ユーザーのログイン状態を判定する基礎ツールの作成
- ログイン必須のコントローラーを保護するconcernの追加
- ユーザーとロールの紐付け方法
Auth0をはじめとする認証サービスを活用すれば、ほとんどコードを書かずに最先端の認証機能をRuby on Railsアプリケーションに組み込めます。認証レイヤーを自前で実装したり、DeviseのようなGemに頼ったりするよりも、はるかに良い選択肢となることが多いでしょう。
それでは、Happy coding!
P.S. Ruby Magicの記事を公開後すぐにお読みになりたい方は、Ruby Magicニュースレターをご購読ください。すべての記事をお見逃しなく!
Thomas Riboulet(トーマス・リブレ)
ゲスト執筆者のThomasは、フランス拠点のバックエンドおよびクラウドインフラエンジニア(コンサルタント)です。13年以上にわたり、スタートアップや企業のチーム・プロダクト・インフラのスケーリングに携わってきました。フランスのGNU/Linux雑誌や自身のブログにも多数寄稿しています。
Thomas Ribouletの記事一覧
-
Rubyのラムダ徹底解説――基本から実践的な応用テクニックまで
Rubyにおいてブロックは非常に重要な存在であり、ブロックなしにこの言語を語ることはできません。では、ラムダはどうでしょうか?ラムダを愛している人はいるのでしょうか?実際のところ、何年もラムダを使わずに過ごすことだって可能かもしれません。まるで昔の時代の遺物のように見えることもあるでしょう。 しかし、それは完全な真実ではありません。少し掘り下げてみると、ラムダには興味深い技が数多く隠されているのです。 この記事では、まずラムダの基本的な使い方から始め、その後、より高度で面白い応用へと進んでいきます。すでに毎日ラムダを使いこなしている方は、ぜひ後半の応用編までスクロールしてください。 ラムダにつ
-
Rubyで例外発生時にローカル変数とインスタンス変数をログに記録する方法
簡単には再現できないバグに悩まされたことはありませんか?アプリをしばらく使い続けたユーザーの環境でだけ発生し、エラーメッセージやバックトレースを見ても原因がさっぱり分からない——そんな経験を持つ開発者は多いはずです。 こうした場面で役立つのが、例外が発生する直前のアプリの状態をスナップショットとして記録しておく手法です。たとえば、すべてのローカル変数とその値の一覧を取得できれば、デバッグの強力な手がかりになります。実は、これは思ったより簡単に実現できるのです。 この記事では、例外発生時点でのローカル変数をキャプチャする方法を紹介します。ただし、最初に重要な注意点があります。ここで紹介するテ