Gokul595/api_guard

[Question] How to set a cookie in authentication response?

Closed this issue · 1 comments

I'm building a hybrid app with Turbo and want to set the session cookie when signing in via the API. The client will then pass this cookie to the web view to sign in there.

I've wired up my custom controller via routes but am running into an issue when using #sign_in from Devise. Here's my controller, the only line that is different is the call to #sign_in.

module Users
  class AuthenticationController < ApiGuard::AuthenticationController
    before_action :find_resource, only: [:create]

    def create
      if resource.authenticate(params[:password])
        create_token_and_set_header(resource, resource_name)
        sign_in("User", resource) # This line is the only change.
        render_success(message: I18n.t("api_guard.authentication.signed_in"))
      else
        render_error(422, message: I18n.t("api_guard.authentication.invalid_login_credentials"))
      end
    end

    private

    def find_resource
      self.resource = resource_class.find_by(email: params[:email].downcase.strip) if params[:email].present?
      render_error(422, message: I18n.t("api_guard.authentication.invalid_login_credentials")) unless resource
    end
  end
end

Successfully authenticating raises the following error:

RuntimeError (Could not find a valid mapping for #<User id: 1, email: "joe@masilotti.com", created_at: "2021-03-14 04:34:15.068574000 +0000", updated_at: "2021-03-17 00:03:05.959170000 +0000">):

app/controllers/users/authentication_controller.rb:8:in `create'

Is it not possible to use Devise methods here? I feel like I'm missing something obvious and any help would be greatly appreciated!

Actually, I think I figured it out! They key is the manual mapping of class_name: "User" in routes.rb. I also simplified the controller to be only what I need.

# app/controllers/users/authentication_controller.rb
module Users
  class AuthenticationController < ApiGuard::AuthenticationController
    def create
      super
      sign_in(resource) if response.ok?
    end
  end
end
# config/routes.rb
Rails.application.routes.draw do
  devise_for :users, class_name: "User"

  # ...

  scope path: :api do
    api_guard_routes for: "users", controller: {
      authentication: "users/authentication"
    }
  end
end