Rails でのデバイスのマスタリング:OmniAuth、API Auth、および Authtrail
このシリーズのパート 1 では、サンプル アプリを使用してモジュール、ヘルパー、ビュー、コントローラー、ルートを探索する Devise を紹介しました。
このパートでは、Devise のより高度な使用法、特に OmniAuth、API 認証、Authtrail の使用法について説明します。
早速始めてみましょう!
Ruby の OmniAuth による認証
現在では、ほぼすべての Web アプリケーションで、Twitter や Facebook などのソーシャル ネットワークから Google、GitHub などに至るまで、幅広い認証プロバイダを介してログインするオプションが提供されています。
多くの場合、この便利なマルチプロバイダー認証は、OmniAuth と呼ばれるライブラリによって強化されます。 OmniAuth は、複数の外部プロバイダーとの統合を可能にする、Ruby 用の柔軟で強力な認証ライブラリです。
さまざまな OAuth プロバイダーに接続するためのシンプルで統合された API を提供します。 OmniAuth は、ソーシャル メディア アカウントを使用してサインアップまたはログインするオプションをユーザーに提供したい場合に特に役立ちます。 OmniAuth を使用すると、Rails アプリケーションにソーシャル ログイン機能を簡単に追加できます。
OmniAuth を Devise gem と併用すると、ユーザーの認証と認可の管理がさらに簡単になります。外部プロバイダーのサインイン オプションに OmniAuth を使用しながら、Devise の組み込み認証機能を利用できます。
OmniAuth と Devise の使用を開始する
前述したように、OmniAuth を使用すると、多数のサードパーティ認証プロバイダーと統合できます。この記事では、GitHub を使用します。
OmniAuth Gems をインストールする
アプリの Gemfile 内 に、次の行を追加します。
OmniAuth 2.0+ gem を使用している場合は、以下も追加する必要があります。
omniauth-rails_csrf_protection gem は、すべての GET を保証します。 OAuth フローへのリクエストは無効になります。また、OAuth リクエストフェーズの前に Rails CSRF トークン検証ツールも挿入されます。これら 2 つのアクションは、OAuth 認証フローを狙ったクロスサイト フォージェリ攻撃を軽減することを目的としています。
次に、bundle install を実行します。 gem をインストールします。
新しい GitHub OAuth アプリを作成する
次に、GitHub 上に新しい OAuth アプリを作成する必要があります。このアプリは、必要に応じて簡単に取り消すことができる認証権限を持つユーザーとして機能します。
最初のステップは、GitHub アカウント プロファイルの設定ページに移動することです。次に、左側のメニューで「開発者設定」をクリックします。次のような画面が表示され、新しい OAuth アプリを作成できます。

「新規アプリケーションの登録」をクリックすると、次のような画面が表示されます。

次のようにフォームの詳細を入力します。
- アプリケーション名 - 新しい OAuth アプリに適切な名前を付けます。
- ホームページの URL - 現時点では、
http://localhost:3000/を使用してください。 。本番環境では、アプリの実際のホームページ URL を使用します。 - アプリケーションの説明 - 必須ではありませんが、多数のアプリがあり、それらを区別する必要がある場合は、1 つ持っていても構いません。
- 認可コールバック URL - これは必須の入力であり、通常は
http://<app-url>/users/auth/<application-provider>/callbackのような OAuth コールバック URL 形式に従います。 。ただし、Google などの一部の OAuth プロバイダはこの形式に従っていない可能性があるため、その点に注意する必要があります。
それが完了したら、「アプリケーションを登録」をクリックします。次の画面で、新しいアプリ シークレットを生成し、安全な場所にメモします (一度しか表示されないため)。
Devise イニシャライザを構成する
Devise イニシャライザ config/initializers/devise.rb を開きます。 そして、GitHub に固有の OmniAuth セクションに移動します。コメントアウトされる可能性が高いため、コメントを解除し、新しい GitHub OAuth アプリの ID とシークレットを使用して編集します。
OmniAuth コールバック コントローラを作成する
すでに Devise コントローラーを生成している場合は、OmniauthCallbacksController が見つかります。 それに応じてカスタマイズする準備ができています。そこにない場合は、手動で作成し、次のように編集します。
上記のコードについて注意すべき点がいくつかあります。
from_omniauthこれはUser内に実装するメソッドです。 モデル。sign_in_and_redirectは OAuth 内のメソッドです。
移行を追加してユーザー モデルを変更する
次に、User モデルにいくつかの列、特に provider を追加する必要があります。 列と uid 列:
bundle exec rails db:migrate を実行します このステップを完了するには。
Devise モデルをオムニア認証可能にする
ここでは、User を編集する必要があります。 Devise Omniauthable モジュールを追加してモデル化します。
この後に、from_omni_auth を追加します。 方法。これは Users::OmniauthCallbacksController から呼び出されます。 先ほど設定したもの:
あとは、ログイン リンクを Devise ビューに追加することだけです。
ログイン リンクを設定する
デフォルトでは、Devise はユーザー登録ビューとログイン ビューに適切なプロバイダーのログイン リンクを自動的に追加します。このリンクは GET を使用します。 メソッドですが、OmniAuth 2.0 以降では POST が優先されることがわかっています。 リクエスト。したがって、リンクを無効にし、POST を使用して独自のリンクを挿入する必要があります。 リクエスト:
これで、Devise と GitHub OAuth 認証を使用して Ruby on Rails 7 アプリをセットアップすることができました。コンパニオン アプリの完全なソース コードはここから入手できます。
次に、別の高度な使用例、つまり Devise を使用して API 呼び出しを認証することに取り掛かります。
Devise for Ruby を使用した API 認証
現在、ユーザーが API 経由でアプリに接続できることを期待することは珍しくありません。このセクションでは、Devise を使用してそのようなユーザー リクエストを安全に認証する方法を見ていきます。
ブラウザベースの認証は通常 Cookie ベースですが、ほとんどの API 認証は、ヘッダー内で渡される JSON Web トークン (または単に JWT) と呼ばれるトークンを介して行われます。
ヒント :このセクションでは、Rails API のみのアプリを使用していると仮定します。手順に従って、rails new app_name --api を使用して作成します。
JWT ベースの認証フロー
前述したように、API 認証は JWT トークンに基づいており、JWT ベースの認証フローがどのように発生するかを理解することが重要です。基本的には、以下に示す一般的な手順に従います。
- ユーザー クライアントが API アプリを呼び出します。
- API アプリは、Cookie の代わりに使用できる認証トークンである JSON Web Token (JWT) で応答します。
- ユーザークライアントによる後続のリクエストは、
Authorizationのこのトークンを使用して行われます。 ヘッダー。 - その後、ユーザーは Devise の「セッション破棄」アクションを実行できるようになり、その結果、トークンが破棄され、ユーザーはログアウトされます。
ここで、クロスオリジン リソース共有 (CORS) と呼ばれるものから始めて、このフローを実行してみましょう。
CORS のセットアップ
CORS は、外部ソースからのリクエストを許可するように API アプリを設定します。 CORS は、アプリケーションによる外部リクエストの処理方法を定義する HTTP ベースのセキュリティ ポリシーです。デフォルトでは、CORS は、最初のリクエストを行ったドメインとは異なるドメインから発信されたリクエスト (つまり、異なる「発信元」からのリクエスト) をブロックします。
CORS を適切に処理するには、気の利いた gem rack-cors を使用します。 。 Gemfile 内 、以下の行のコメントを解除して、bundle install を実行します。 :
また、対応する CORS 初期化ファイルを開いて、以下のように変更します。
ここまでの作業に関する重要な注意事項:
origins "*"- 単に、API アプリが他のソースからのリクエストを受信できるようになるという意味です。expose: %w[Authorization Uid]- デフォルトでは、rack-corsgem は認可ヘッダーと UID ヘッダーを公開しませんが、認可トークンを渡すのでそれらが必要です。
それが完了したら、Devise とそれに付随する Devise-JWT gem をインストールしましょう。
Devise および Devise-JWT Gems を Rails アプリに追加する
devise-jwt gem は、JWT トークンを操作できるようにする Devise の拡張機能です。ジェムを Gemfile に追加します 次に、bundle install を実行します。 :
Devise インストール ジェネレーター bundle exec rails g devise:install を実行します。 .
モデルの生成と構成
2 つのモデルを設定する必要があります:通常の Devise ユーザー モデル (bundle exec rails g devise User) )、取り消し戦略に使用するモデル (つまり、ユーザーが API からサインアウトする方法):
JWT トークン認証可能モジュールを追加し、2 番目のモデル JwtDenylist を使用するトークン失効戦略を定義することで、API 認証用の通常の Devise ユーザー モデルを変更します。 :
次に、使用する失効戦略と失効テーブルを参照して、2 番目のモデルを構成します。
次のセクションでは、トークンの取り消しと、それが必要な理由について概説します。
トークン取り消しの重要性
トークンの取り消しが重要なのはなぜですか? JWT トークンはステートレスであるためです。サーバーは、署名以外にはそれらについて何も知りません。このようなシナリオでは、サーバーには、対応するトークンを取り消してユーザーをサインアウトする方法がありません。個々のトークンを取り消す方法はないため、トークンを構築し、それを使用するようにサーバーに指示する必要があります。
トークンを取り消すとき、内部で実際に起こっていることは、トークンの一意の部分である jti です。 (JWT ID) は、定義された失効戦略に従って抽出され、使用されます。
もちろん、これにより、トークン失効戦略とは何かという別の疑問が生じます。一言で言えば、これはサーバーによるトークンの取り消しの処理方法の定義です。失効には 3 つの基本的な戦略があります。
- JTIMatcher 戦略 - ここでは、「jti」と呼ばれる固有の列がユーザー モデルに追加されており、失効テーブルとしても機能します。ユーザーがリクエストを行うたびに、
jtiヘッダー内の は保存されたトークンと照合され、一致が見つかった場合にのみアクセスが許可されます。 - 拒否リスト戦略 - この場合、
jtiおよびトークンの有効期限 (exp) 取り消されたトークンの数)はデータベース テーブルに保存されます。ユーザーが行ったリクエストごとに、このテーブルに対してユーザーの現在のトークンjtiと比較するチェックが行われます。 データベース内の取り消されたものに対して。一致するものが見つかった場合、そのユーザーのリクエストは拒否されます。 - 許可リスト戦略 - ある意味、この戦略は最初の戦略に似ていますが、JWT ID を格納するテーブルがユーザー トークンを格納する別のテーブルと 1 対多の関係にある点が異なります。リクエストが行われるたびに、ユーザーの
jtiホワイトリスト テーブルに格納されているものは、トークンを使用して照合テーブルに格納されているものと照合されます。一致するものが見つかった場合にのみアクセスが許可されます。
明らかに、これはトークン失効の非常に簡略化された概要であり、詳細についてはここで学ぶことができます。
JWT トークンの署名キーを設定する
安全なトークンを使用してユーザーとそのリクエストを認証するため、トークンに署名する方法が必要です。ここで秘密鍵が登場します。Rails 秘密鍵 secret_key_base とは異なる新しい鍵を生成することをお勧めします。 .
bundle exec rake secret を実行します 一意のキーを生成するには、Devise イニシャライザを編集してこのキーを含めます。
最後に、コントローラーを設定しましょう。
コントローラのセットアップ
API 認証用に Devise を実装する最後のステップは、コントローラーを設定することです。簡単にするために、2 つのコントローラーをセットアップします。1 つは登録を処理し、もう 1 つはセッション用です。
登録コントローラから始めて、これらを手動で作成しましょう。
このコントローラで何が起こっているかは次のとおりです。
- JSON でリクエストに応答するように構成します。
respond_withを指定します。 登録の成功または失敗の結果を返すアクション。
次に、セッション コントローラについて説明します。
登録コントローラーと同様に、ここではコントローラーが JSON で応答することを指定します。 respond_with も定義します。 ユーザーがログインに成功したときのアクションと respond_to_on_destroy ユーザーのサインアウトを処理します。
これにより、Devise トークンと JWT トークンを活用した API 認証フローが動作するようになります。
最後のセクションでは、Devise と Authtrail を使用してユーザーのログインを追跡する方法を簡単に説明します。
Authtrail を使用したデバイスのログインの追跡
誰かがアカウントにログインするたびに、IP アドレスやログインのタイムスタンプなどの詳細を含む通知メールをアプリのユーザーに送信したいとします。どうすればこれを達成できますか?
ユーザーのログインを追跡し、その情報をユーザーに送信する通知メールで使用する必要があります。ただし、その前に、ユーザーのログインを追跡する方法が必要です。これは、Authtrail と呼ばれる気の利いた gem を使用して実現できます。これも Devise とうまく組み合わせられます。
Authtrail のインストール
最初のステップは、bundle add authtrail を使用して gem をインストールすることです。 。さらに、電子メールや IP アドレスなどのユーザーを特定できる情報をアプリ データベースに保存することになるため、実稼働環境では Lockbox と Blindindex gem を組み合わせてこのデータを暗号化することを強くお勧めします。
次に、Authtrail ジェネレーターを実行して、そのイニシャライザーと、ログイン データを保存する付随するテーブル移行を作成します。
Authtrail の仕組み
ユーザーがログインしようとするたびに、次の重要な詳細を含む新しい Authtrail レコードが作成されます。
- 使用されるログインメールアドレス
- ログインが成功したかどうか
- ログインが失敗した理由 (ログインが失敗した場合)
- ユーザーの IP アドレス、
referrerなど
この情報は必要に応じて使用できます。たとえば、電子メールと IP アドレスの情報を含む通知電子メールをユーザーに送信して、自分のアカウントでログインが試行されたことを知らせることができます。
Authtrail のドキュメントを参照して、利用可能なすべての可能性を確認してください。
まとめ
このシリーズでは、Devise gem について詳しく説明しました。
まず、Devise のモジュール、ヘルパー、ビュー、コントローラー、ルートがどのように機能するかなど、Devise の基本を理解しました。この 2 番目で最後のパートでは、OAuth、Authtrail、および API 認証で Devise を使用する方法を検討しました。
このシリーズが、Devise 認証に関するすべての有益なガイドとして役立つことを願っています。
コーディングを楽しんでください!
追記Ruby Magic の投稿を報道後すぐに読みたい場合は、Ruby Magic ニュースレターを購読して、投稿を 1 つも見逃さないようにしてください。
-
RubyのSOLID設計原則
すべてのソフトウェアアプリケーションは時間とともに変化します。ソフトウェアに加えられた変更は、予期しないカスケードの問題を引き起こす可能性があります。ただし、変更しないソフトウェアは構築できないため、変更は避けられません。ソフトウェア要件は、ソフトウェアの成長とともに変化し続けます。私たちにできることは、変更に対して回復力のある方法でソフトウェアを設計することです。ソフトウェアを適切に設計することは、最初は時間と労力を要する可能性がありますが、長期的には時間と労力を節約します。緊密に結合されたソフトウェアは壊れやすく、変更によって何が起こるかを予測することはできません。設計が不十分なソフトウェ
-
Ruby転置法を使用して行を列に変換する
今日は、Ruby転置法を使用してRubyでグリッドを処理する方法を学習します。 多次元配列の形をした完璧なグリッド、たとえば3×3の正方形があると想像してみてください。 そして、行を取得して列に変換する 。 なぜあなたはそれをしたいのですか? 1つの用途は、古典的なゲームであるtic-tac-toeです。 ボードをグリッドとして保存します。次に、勝利の動きを見つけるには、行を確認する必要があります 、列 &対角線 。 問題は、グリッドを配列として格納している場合、行に直接アクセスすることしかできないことです。 コラムズザハードウェイ 「直接アクセス」とは、配列を(eachで)調べ