ysk91_engineer
@ysk91_engineer (.S 佑介)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Deviseでsign_inしたユーザー情報を更新するとログアウトしてしまう

解決したいこと

RailsアプリにてDeviseをカスタマイズして使用しています。
userに対してsign_inメソッドをした後にユーザー情報を更新するとログイン状態を失ってしまうのを解決したいです。

発生している問題・エラー

sign_in後にusers/resistrations#updateするとログアウトしてしまう。

考えられる原因

  • user情報がcookieに保存されていない?
  • ログイン中のuser_sessionの中身が空

該当するソースコード

GitHub

users/resistrations_controller.rb
# frozen_string_literal: true

class Users::RegistrationsController < Devise::RegistrationsController

  def new
    @user = User.new
  end

  def create
    @user = User.new(users_params)
    if @user.save
      sign_in(:user, @user)
      redirect_to categories_path, notice: "新規ユーザー「#{@user.name}」を登録しました。"
    else
      render 'new'
    end
  end

  def edit
    @user = User.find(params[:id])
  end

  def update
    @user = User.find(params[:id])
    if @user.update(users_params)
      redirect_to categories_path, notice: "ユーザー「#{@user.name}」を更新しました。"
    else
      render 'edit'
    end
  end

  private

  def users_params
    params.require(:user).permit(:name, :email, :password)
  end
end
users/sessions_controller.rb
# frozen_string_literal: true

class Users::SessionsController < Devise::SessionsController

  def new
  end

  def create
    @user = User.find_by(email: params[:session][:email])
    if @user.valid_password?(params[:session][:password])
      sign_in(@user)
      @user.update!(remember_created_at: Time.zone.now) # ログインと同時にremember_created_atをtrueにしたが効果なし
      redirect_to categories_path, notice: "#{@user.name} としてログインしました"
    else
      render 'new', notice: "ログインに失敗しました"
    end
  end

  def destroy
    super
  end

  private

  def sessions_params
    params.require(:session).permit(:email, :password)
  end
end

ログイン前のセッション情報

#<ActionDispatch::Request::Session:0x0000ffff88e89418 @by=#<ActionDispatch::Session::CookieStore:0x0000aaaad8146850 @app=#<ActionDispatch::ContentSecurityPolicy::Middleware:0x0000aaaad8146a80 @app=#<ActionDispatch::PermissionsPolicy::Middleware:0x0000aaaad8146be8 @app=#<Rack::Head:0x0000aaaad8146d28 @app=#<Rack::ConditionalGet:0x0000aaaad8146eb8 @app=#<Rack::ETag:0x0000aaaad81470e8 @app=#<Rack::TempfileReaper:0x0000aaaad8147228 @app=#<Warden::Manager:0x0000aaaad8147660 @config={:default_scope=>:user, :scope_defaults=>{}, :default_strategies=>{:user=>[:rememberable, :database_authenticatable]}, :intercept_401=>false, :failure_app=>#<Devise::Delegator:0x0000aaaad8d98b30>}, @app=#<ActionDispatch::Routing::RouteSet:0x0000aaaad60bfa50>>>, @cache_control="max-age=0, private, must-revalidate", @no_cache_control="no-cache">>>>>, @default_options={:path=>"/", :domain=>nil, :expire_after=>nil, :secure=>false, :httponly=>true, :defer=>false, :renew=>false}, @key="_myapp_session", @cookie_only=true, @same_site=nil>, @req=#<ActionDispatch::Request GET "http://localhost:3000/" for 172.24.0.1>, @delegate={"session_id"=>"3e0f96fd619df6bf8577df7f6428c8ce", "_csrf_token"=>"IvC9M-tK54_GQq61E-NVvdnU9eyRA4vR9_WbdCQh6GM=", "warden.user.user.session"=>{}, "user_return_to"=>"/categories"}, @loaded=true, @exists=true>

スクリーンショット 2023-02-16 15.24.51.png

ログイン後のセッション情報

#<ActionDispatch::Request::Session:0x0000ffff75c70838 @by=#<ActionDispatch::Session::CookieStore:0x0000aaaad8146850 @app=#<ActionDispatch::ContentSecurityPolicy::Middleware:0x0000aaaad8146a80 @app=#<ActionDispatch::PermissionsPolicy::Middleware:0x0000aaaad8146be8 @app=#<Rack::Head:0x0000aaaad8146d28 @app=#<Rack::ConditionalGet:0x0000aaaad8146eb8 @app=#<Rack::ETag:0x0000aaaad81470e8 @app=#<Rack::TempfileReaper:0x0000aaaad8147228 @app=#<Warden::Manager:0x0000aaaad8147660 @config={:default_scope=>:user, :scope_defaults=>{}, :default_strategies=>{:user=>[:rememberable, :database_authenticatable]}, :intercept_401=>false, :failure_app=>#<Devise::Delegator:0x0000aaaad8d98b30>}, @app=#<ActionDispatch::Routing::RouteSet:0x0000aaaad60bfa50>>>, @cache_control="max-age=0, private, must-revalidate", @no_cache_control="no-cache">>>>>, @default_options={:path=>"/", :domain=>nil, :expire_after=>nil, :secure=>false, :httponly=>true, :defer=>false, :renew=>false}, @key="_myapp_session", @cookie_only=true, @same_site=nil>, @req=#<ActionDispatch::Request GET "http://localhost:3000/" for 172.24.0.1>, @delegate={"session_id"=>"022abbc009afdcb4aaf700704ab49f91", "_csrf_token"=>"IvC9M-tK54_GQq61E-NVvdnU9eyRA4vR9_WbdCQh6GM=", "warden.user.user.session"=>{}, "user_return_to"=>"/categories", "warden.user.user.key"=>[[1], "$2a$12$U.h0GdPjs5fz/Y7NkFp9w."]}, @loaded=true, @exists=true>

スクリーンショット 2023-02-16 15.26.36.png
(↑赤文字の下に表示されている{}user_session)

自分で試したこと

  • sign_inでログインしたユーザー情報をcurrent_userにて取得可能
  • ログイン後にbefore_action :authenticate_user!は機能している
  • ログイン後に/sign_up/loginパスへのアクセスをブロックしている(正常)
  • user_signed_in?は機能している
  • users/sessions#createにてUserモデルのremember_created_atに現在時刻を代入し、trueにしても効果無し
  • こちらのサイトの通りにしても効果なし

参考にしたサイト

0

4Answer

パスワードを変更するとログアウトされるのは devise の標準の機能です。
(たとえ同じパスワードでもフィールドをセットしているとそうなります)
これが望ましくない場合、

  • password を更新するのをやめる
    • (registrations_controller の場合) password param を送るのをやめる
  • Devise の config で sign_in_after_reset_passwordtrue にする
  • update 後に sign_in :user, @user, bypass: true で強制的に再ログインさせる

のどれかでできます。

参考:

あと余談ですが、個人的には、ユーザの編集は users controller でやって、 regstrations controller は使うとしてもメールが届かない時の変更用、くらいで良いんじゃないかという気はします。

2Like

Comments

  1. @ysk91_engineer

    Questioner

    コメント頂きありがとうございます!

    機能に関しては上の@shu-illy様の方法で実装できました。

    コントローラの分け方についてアドバイスありがとうございます!
    なるほど、そのようにコントローラを分けてしまう方法もあるのですね、、
    勉強になりました!

device使ったことないですが。。

・ユーザの現在時刻へのアップデートは出来たんでしょうか?
・ログには何か表示されてないでしょうか?
・アップデートができてない場合は「rails device ユーザー更新」のように調べるのもいいかと思います

1Like

Comments

  1. @ysk91_engineer

    Questioner

    コメントありがとうございます!
    確かに、もう少しログをよく見てみたら何かヒントはあったかもしれません汗

    ユーザーの現在時刻はアップデートできたのですが、なかなか上手くいかず、、という状況でした。
    下のお三方のコメントを参考に対処したところ今回の機能を無事に実装できました。

    コメントいただきありがとうございました^^

Comments

  1. @ysk91_engineer

    Questioner

    コメントありがとうございます!

    おっしゃる通り、パスワードも更新していました。
    下の@shu-illy様がおっしゃる通り、Deviseはパスワード更新と同時にログアウトする設計なのですね、、

    ヒントを頂きありがとうございました!

Comments

  1. @ysk91_engineer

    Questioner

    ありがとうございます!

    こちらの記事を参考にしたところ、無事に実装できました!
    大感謝です!!

    後ほど、本件を記事にまとめて自分の力になるようにいたします!

Your answer might help someone💌