web-dev-qa-db-ja.com

devise gemを使用して確認リンクをクリックした後のサインインを回避しますか?

devise gemを使用しています。確認リンクをクリックした後、直接サインインします。現在、再度サインインするよう求めています。

最近、私はdevise初期化ファイルに以下を追加しました:

config.allow_insecure_token_lookup = true
config.secret_key = 'a8d814803c0bcc735ce657adc77793459d00154cdd7532c13d3489600dc4e963f86e14beb593a32cbe9dbbe9197c9ce50a30102f363d90350052dc8d69930033'

助言がありますか?

38
Durga Prasad

以前のバージョンのDeviseでは、ユーザーは確認後に自動的にサインインしていました。これは、確認の電子メールにアクセスできるすべてのユーザーが、リンクをクリックするだけで誰かのアカウントにサインインできることを意味しました。

ユーザーを自動的にサインインさせることも、電子メールの再確認ワークフローに悪影響を及ぼす可能性があります。ユーザーが自分の電子メールアドレスを変更することを決定し、その間に、新しい電子メールアドレスにタイプミスをしたとします。電子メールは別のアドレスに送信され、トークンを入手すると、そのアカウントにサインインできます。

ユーザーが電子メールをすぐに修正しても、害はありません。しかし、そうでない場合、他の誰かがそのアカウントにサインインする可能性があり、ユーザーはそれが発生したことを知りません。

このために、 Devise 3.1確認後にユーザーを自動的にサインインしなくなりました。 config/initializers/devise.rbで以下を設定することにより、アップグレード後に古い動作を一時的に戻すことができます。

config.allow_insecure_sign_in_after_confirmation = true

このオプションは、移行を支援するために一時的にのみ使用できます。

61
Rajarshi Das

config.allow_insecure_sign_in_after_confirmationフラグはDeviseではサポートされなくなりました。

ユーザーが自分のアカウントを確認したときに自動的にログインすることで起こり得るセキュリティ上の懸念に注意する必要があります( http://blog.plataformatec.com.br/2013/08/devise-3-1-now-with -more-secure-defaults / )。一部のアプリでは、ユーザーエクスペリエンスの面でのメリットはセキュリティのトレードオフに値する場合があります。

結局のところ、セキュリティ上のリスクとは、a)ユーザーがメールアドレスを間違って入力した、b)ミスをすぐに修正しない、c)入力したメールが有効で機能するメールに対応している、d)誤って受信した人メールはそれを開き、リンクをクリックします。

これがアプリケーションにとって許容できるリスクプロファイルである場合は、デバイスのConfirmationsControllerをオーバーライドできます。

class ConfirmationsController < Devise::ConfirmationsController
  def show
    self.resource = resource_class.confirm_by_token(params[:confirmation_token])
    yield resource if block_given?

    if resource.errors.empty?
      set_flash_message(:notice, :confirmed) if is_flashing_format?
      sign_in(resource) # <= THIS LINE ADDED
      respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
    else
      respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render :new }
    end
  end
end

routes.rb

devise_for :users, controllers: { confirmations: 'confirmations' }
52
Louis Simoneau

Deviseの最新バージョンでは、次のことができます。

config/routes.rb

devise_for :users, controllers: { confirmations: 'users/confirmations' }

app/controllers/users/confirmations_controller.rb

class Users::ConfirmationsController < Devise::ConfirmationsController
  def show
    super do |resource|
      sign_in(resource)
    end
  end
end
16
Sjors Provoost

Mb21の答えを見ると、

def show
  super do |resource|
    if resource.confirmation_sent_at > DateTime.now-2.hours && resource.errors.empty?
      sign_in(resource)
    end
  end
end

confirm_sent_atは、メールがユーザーに送信された時刻です。これは、confirmed_atとは対照的です。これは、ユーザーがリンクをクリックした瞬間であり、サーバー上で常に2時間以内に発生します。

3
RAM

ユーザーが作成してから2時間以内にメール内のリンクをクリックした場合、ユーザーが自動的にサインインするようにしたかったので、 @Sjorの回答に基づいて、私たちは次のように行きました:

class ConfirmationsController < Devise::ConfirmationsController
  def show
    super do |resource|
      if resource.confirmed_at > DateTime.now-2.hours && resource.errors.empty?
        sign_in(resource)
      end
    end
  end
end
1
mb21

ここには、それを解決する方法があります。

このコードにより、ユーザーは確認後に初めて自分のアカウントを確認する場合にのみ、自動的にサインインできます。

class ConfirmationsController < Devise::ConfirmationsController
  before_action :maybe_auto_sign_in, only: :show

  protected

  def after_confirmation_path_for(resource_name, resource)
    sign_in(resource) if @auto_sign_in
    super
  end

  private

  # Automatically sign in the user that confirmed his/her email first time.
  def maybe_auto_sign_in
    @auto_sign_in =
      User.first_time_confirming?(params[:confirmation_token])
  end
end

class User < ActiveRecord::Base
  def self.first_time_confirming?(confirmation_token)
    confirmation_token &&
      User.where(confirmation_token: confirmation_token, unconfirmed_email: nil)
          .exists?
  end
end
1
Mohamed Ziata