[解決済み] deviseのtoken_authenticatableは安全ですか?
質問
シンプルなAPIを構築しています。
RailsのAPI
で簡単なAPIを作っているのですが、ここで正しい道を歩んでいることを確認したいと思います。私はログインを処理するためにdeviseを使用しており、Deviseの
token_authenticatable
オプションを使用することにしました。このオプションは、各リクエストで送信する必要のある API キーを生成します。
私はAPIをバックボーン/マリオネットフロントエンドと組み合わせており、一般的にセッションをどのように扱うべきか疑問に思っています。私の最初の考えは、ローカルストレージまたはクッキーに API キーを保存し、ページロード時にそれを取得することでしたが、その方法で API キーを保存することについては、セキュリティの観点から気になることがありました。ローカルストレージやクッキーを見たり、通過したリクエストをスニッフィングすることで、簡単にapiキーを取得し、それを使って無期限にそのユーザーになりすますことができるのではないでしょうか?私は現在、ログインのたびにapiキーをリセットしていますが、それでも頻繁なようです。どのデバイスでログインしても、他のデバイスではログアウトしてしまうことになり、ちょっと面倒です。このリセットがなくなれば、ユーザビリティの面でも改善されるような気がします。
私はここで完全に間違っているかもしれませんが (そうであることを望みます)、この方法で認証することが確実に安全であるかどうか、また、そうでない場合、良い代替案は何か、どなたか説明していただけないでしょうか。全体として、私は、頻繁に再認証を強制することなく、ユーザーが API アクセスに「サインイン」している状態を安全に維持できる方法を探しています。
どのように解決するのですか?
token_authenticatable
はタイミング攻撃に対して脆弱です。
このブログ記事
. これらの攻撃は
token_authenticatable
が Devise 3.1 で削除された理由です。を参照してください。
plataformatec ブログ記事
をご覧ください。
最も安全なトークン認証の仕組みを持つために、トークンを
-
HTTPS 経由で送信する必要があります。
-
暗号強度のあるランダムなものである必要があります。
-
安全に比較されなければなりません。
-
データベースに直接保存してはならない。トークンのハッシュのみ保存可能です。(トークン = パスワードであることを忘れないでください。パスワードを平文でデータベースに保存することはありませんよね)
-
何らかのロジックに従って期限切れになるはずです。
使いやすさを優先してこれらの点のいくつかを見送ると、可能な限り安全でないメカニズムになってしまいます。それはとてもシンプルなことです。最初の 3 つの要件を満たし、データベースへのアクセスを制限すれば、十分に安全であるはずです。
私の答えを拡大解釈して説明します。
-
HTTPSを使用する . これはスニッファーに対処するため、間違いなく最も重要なポイントです。
HTTPSを使用しない場合、多くのことがうまくいかない可能性があります。たとえば
-
ユーザーの認証情報(ユーザー名/メールアドレス/パスワード)を安全に送信するためには、ダイジェスト認証を使用しなければなりませんが を使用する必要がありますが、塩漬けハッシュはブルートフォースされる可能性があるため、最近ではこの方法では不十分です。 .
-
Rails 3では、CookieはBase64エンコーディングで覆い隠されているだけなので、かなり簡単に明らかにすることができます。以下をご覧ください。 Railsのセッションクッキーをデコードする をご覧ください。
しかしRails 4以降、Cookieストアは暗号化され、データはデジタル的に検証され、攻撃者には読めなくなりました。クッキーが安全であるのは
secret_key_base
が漏れない限り、Cookieは安全です。
-
-
でトークンを生成します。
-
SecureRandom.hex
は、Ruby 2.5 以上の場合のみです。 -
gemは
sysrandom
を使用すると、古いRubyであれば
なぜこれが必要なのかの説明については、以下のサイトを読むことをお勧めします。
sysrandom
のREADMEとブログの記事 様々なプログラミング言語で安全な乱数を生成する方法 . -
-
ユーザーのIDやメールなどの属性を使って、ユーザーレコードを探します。そして、そのユーザーのトークンとリクエストのトークンを比較し
Devise.secure_compare(user.auth_token, params[:auth_token]
. Rails 4.2.1+を使用している場合は、次のようにすることもできます。ActiveSupport::SecurityUtils.secure_compare
.行う ではなく のようなRailsのファインダでユーザレコードを検索します。
User.find_by(auth_token: params[:auth_token])
. これはタイミング攻撃に弱い! -
もし、ユーザーごとに複数のアプリケーション/セッションを同時に使用するのであれば、2つの選択肢があります。
-
暗号化されていないトークンをデータベースに保存して、デバイス間で共有できるようにする。これは悪い習慣ですが、UX の名において (そして DB アクセスを従業員に任せている場合)、そうすることができるのでしょう。
-
現在のセッションを許可したい数だけ、ユーザーごとに暗号化されたトークンを保存します。したがって、2 つの異なるデバイスで 2 つのセッションを許可したい場合、2 つの異なるトークン ハッシュをデータベースに保存します。このオプションは、実装が少し簡単ではありませんが、間違いなく安全です。また、トークンを無効にすることで、特定のデバイスで現在進行中のセッションを終了させることができます (たとえば GitHub やFacebookがそうであるように)。
-
-
トークンを失効させる何らかのメカニズムが必要です。このメカニズムを実装する際には、UXとセキュリティのトレードオフを考慮してください。
Googleは6ヶ月間使用されないとトークンを失効させる .
Facebookは2ヶ月間使用されなかった場合、トークンを失効させます。 :
FacebookのSDKを使用するネイティブモバイルアプリは、約60日間有効なアクセストークンを取得します。 トークンを取得します。これらのトークンは、アプリを使用する人が Facebook のアプリケーションにリクエストを送信すると、1 日に 1 回更新されます。 このトークンは、アプリを使用する人がFacebookのサーバーにリクエストを送信すると、1日に1回更新されます。 サーバーにリクエストしたときに更新されます。リクエストがない場合、トークンは約60日後に失効します。 トークンは約60日後に失効し、ユーザーは新しいトークンを取得するために再度ログインする必要があります。 新しいトークンを取得する必要があります。
-
Rails 4にアップグレードして、その暗号化されたCookieストアを使用する。それができない場合は、提案されているように、自分でCookieストアを暗号化します。 はこちら . 暗号化されたクッキーストアに認証トークンを保存することは、全く問題ないでしょう。
また、たとえば、トークンのサブセットまたはデータベース内のすべての単一のトークンをリセットするための rake タスクなど、不測の事態に備えた計画を立てる必要があります。
手始めに、以下のサイトをチェックしてみてください。 この gist (Deviseの著者の一人)で、Deviseでトークン認証を実装する方法を確認してみてください。最後に API のセキュリティに関する Railscast は参考になるはずです。
関連
-
[解決済み】取得中。「プロジェクトのクローンとマイグレート後に、「マイグレーションは保留中です。この問題を解決するには 'bin/rake db:migrate RAILS_ENV=development' を実行してください。
-
[解決済み】TypeError: SymbolからIntegerへの暗黙の変換がない。
-
[解決済み] Railsです。NameError: 初期化されていない定数
-
[解決済み] heroku push rejected, failed to compile Ruby/rails app
-
[解決済み] Devise Admin Roleの追加【終了しました
-
[解決済み] gemのアップデート後、"Asset was not declared to be precompiled in production "でテストが失敗する。
-
[解決済み] 属性を割り当てる場合、引数としてハッシュを渡す必要がある
-
[解決済み] ユーザー名とパスワードでMongoDBを保護する方法
-
[解決済み] 認証とセッション管理に関するSPAのベストプラクティス
-
[解決済み] クロスオリジンリクエストにCookieを設定する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】コントローラでJSONをレンダリングする
-
[解決済み] デバイスを使用する現在のユーザーメソッド
-
[解決済み] ウェブパッカーがアプリケーションを見つけ出せない
-
[解決済み] 変更欄のRailsマイグレーション
-
[解決済み] どなたか、collection_selectをわかりやすく説明していただけませんか?
-
[解決済み] Herokuの問題 : あなたが探しているページは存在しません。
-
[解決済み] Railsで `before_action` での `only:` はどのように機能するのですか?
-
[解決済み] バリデーションなしで属性を更新する方法
-
[解決済み] Railsはsaveでモデル内の検証をスキップしますか?
-
[解決済み] ヘッダーやURLにAPIキーを配置する