devise_token_authのsign_inにてUnpermitted parameters: :user, :sessionエラーが発生

javascript

vue3とrailsAPIにてログイン機能を作成したときに、devise_token_authを使用してログイン機能を作りましたが、Unpermitted parameters: :user, :sessionエラーが発生してしまいました。

原因がわかったので解決方法を解説した記事を作成しました。

Unpermitted parameters: :user, :sessionエラーが発生した状況

vue側はこのようにしていました。email、passwordはv-modelで自動でinputで入力した値が自動で反映されるようになっています。

  const user = ref({
    email: '',
    password: ''
  })
  const login = async() => {
    axios.post('/auth/sign_in', {user: user.value})
    .then((response) => {
      localStorage.setItem("access-token", response.headers["access-token"])
      localStorage.setItem("client", response.headers["client"])
      localStorage.setItem("uid", response.headers["uid"])
      router.push({ path: '/' })
    })
    .catch((error) => {    
    console.log(error)    
  })
  }

ここで、paramsは、{user: user.value}すなわち、{user: {email: ‘入力値’, password: ‘入力値’}}となっています。つづいて、railsの受け取り側は下記になります。

ちなみに、sessionsControllerは作成しましたが、createアクションは作っておらず、devise_token_authのデフォルトのものを使用しています。

原因を追求してみます。

Unpermitted parameters: :user, :sessionの原因追求

devise_token_authのsessions_controllerをappのsessions_controllerにマウントして、中身を確認してみます。

class Auth::SessionsController < DeviseTokenAuth::SessionsController 
   def create
      if field = (resource_params.keys.map(&:to_sym) & resource_class.authentication_keys).first
        q_value = get_case_insensitive_field_from_resource_params(field)

        @resource = find_resource(field, q_value)
      end

      if @resource && valid_params?(field, q_value) && (!@resource.respond_to?(:active_for_authentication?) || @resource.active_for_authentication?)
        valid_password = @resource.valid_password?(resource_params[:password])
        if (@resource.respond_to?(:valid_for_authentication?) && !@resource.valid_for_authentication? { valid_password }) || !valid_password
          return render_create_error_bad_credentials
        end

        create_and_assign_token

        sign_in(@resource, scope: :user, store: false, bypass: false)

        yield @resource if block_given?

        render_create_success
      elsif @resource && !Devise.paranoid && !(!@resource.respond_to?(:active_for_authentication?) || @resource.active_for_authentication?)
        if @resource.respond_to?(:locked_at) && @resource.locked_at
          render_create_error_account_locked
        else
          render_create_error_not_confirmed
        end
      else
        hash_password_in_paranoid_mode
        render_create_error_bad_credentials
      end
    end
end

routes.rbにもルーティングを追加します

mount_devise_token_auth_for 'User', at: 'auth', controllers: {
    registrations: "auth/registrations",
    sessions: 'auth/sessions', # これを追加
  }

とりあえずこれで原因をみていこうと思います。

controllerに渡されるparamを見てみる

binding.pryを設置してcontrollerが取得したparamsを見てみる

class Auth::SessionsController < DeviseTokenAuth::SessionsController 
   def create
      binding.pry # デバッグを追加
      if field = (resource_params.keys.map(&:to_sym) & resource_class.authentication_keys).first
        q_value = get_case_insensitive_field_from_resource_params(field)

        @resource = find_resource(field, q_value)
      end
    end

   ....

end

binding.pryでparamsを取得すると…

[1] pry(#<Auth::SessionsController>)> params
=> #<ActionController::Parameters 
  {"user"=>{"email"=>"wawawa@test.com", "password"=>"wawawa"}, 
    "controller"=>"auth/sessions", 
    "action"=>"create", 
    "session"=>{"user"=>{"email"=>"wawawa@test.com", "password"=>"wawawa"}}} permitted: false>

なんかuserやらsessionやらがparamsの一部として送られてしまっていますね。

sign_in時のparamsで許可されるのは、email、passwordなので、userとかsessionが入ってしまうとおかしいことになります。sign_in時に必要なparamsは、create内のbinding.pryにて下記コマンドで確認できます。

params_for_resource(:sign_in)

sign_in時のpermitパラメータについての詳しい記事はコチラ↓↓

上記の対策をします。

対策① wrap_parameters.rbを修正する

下記のように、wrap_parametersをfalseに設定してみます。

ActiveSupport.on_load(:action_controller) do
  # wrap_parameters format: [:json] コメントアウトにする
  wrap_parameters false  #これを追加する
end

これで実施したところ、エラー文が下記に変わりました!

Unpermitted parameters: :user, :session
↓
Unpermitted parameter: :user

userがまだ残ってしまっているようですね。おそらくparamsで渡す時に、userキーが設定されているのが問題で、それを解消したら何とかなりそう

対策② Unpermitted parameter: :userを対処する

paramsにuserキーが登録されてしまうので、その対処をしていきます。

結論としては下記↓sessions_controllerの最下部に下記を追加する。

  private

  def resource_params
    params.require(:user).permit(*params_for_resource(:sign_in))
  end

ちょっと前にも説明したが、paramsはresource_paramsというdevise_token_authにあるメソッドで取得している。devise_token_authのデフォルトの状態だと、require(:user)が入っていないので、追加してuserキーがついているparamsを取得できるようにする

Unpermitted parameter: :userを対処することができます!

まとめ

結論としては、devise_token_authではparamsの受け取り方が{email:’値’, password:’値’}で受け取る予想をしているが、user:{email:’値’, password:’値’}となっていたことが原因。

対策としては、上記のようにrequire(:user)として、paramsのキーを指定できるようにするか、渡し方をuserキーをつけないようにすることで対処することができます!

コメント

タイトルとURLをコピーしました