bploetz / versionist

A plugin for versioning Rails based RESTful APIs.
MIT License
972 stars 51 forks source link

Devise issue after integrating versionist - "Authentication required for Sign In action" #57

Closed tacticiankerala closed 9 years ago

tacticiankerala commented 10 years ago

We integrated 'versionist' gem for path based versioning for our APIs. After integrating versionist we found that only default sign in/ sign up/password reset urls(Eg: /users/sign_in) are working. The same actions for different versions were giving issues(Eg: /v1/users/sign_in).

We were able to identify that this issue was caused because of the scope. For example, if we are using v1 API then the scope received in Sessions#create is found to be v1_user.

Here is the set up we used,

Routes

 api_version(:module => "v1", :path => {:value => "v1"}) do
   devise_for :users, :controllers => { 
      :registrations => 'v1/registrations',
      :sessions => 'v1/sessions',
      :passwords => 'v1/passwords'
    }   
end

And we got the auth_options inside Sessions#create as

{:scope => :v1_user, :recall => "sessions#new"}

We tried overriding the scope to :user and everything started working.

Similar issues we faced in registrations and passwords controller, where the devise parameters found to be nil for constructing the resource.

Here is our dependencies,

rails (3.2.13)
devise (2.2.3)
versionist (1.2.1)

Right now we have overridden all the required devise actions, is there a better solution to this problem?

bploetz commented 10 years ago

When you say "The same actions for different versions were giving issues(Eg: /v1/users/sign_in)", what exactly happened? Did you get an error? Did it do something unexpected?

Any chance you could distill this down to a skeleton example app which exhibits the problem and throw it up on github somewhere where I can take a look?

twnaing commented 4 years ago

I am also experiencing this problem. With the following route

  namespace :api, defaults: { format: 'json' } do
    api_version(module: 'V1',
                header: { name: 'Accept', value: 'application/vnd.example.com; version=1' },
                path: { value: 'v1' }) do
      scope as: :member, path: :m, module: :member do
        devise_for :customers,
                   path: '',
                   path_names: {
                     sign_in: 'login',
                     sign_out: 'logout',
                     registration: 'signup'
                   }
      end
    end
  end

I get { scope: :api_v1_member_customer ... }. It should only be { scope: :customer ... }

twnaing commented 4 years ago

After reading the source code, I think I have to avoid using the path based versioning to get what I want.

I can successfully authenticate with the following setup.

  scope :member, module: :office do
    scope :api, module: :api, defaults: { format: :json } do
      api_version( module: 'V1', header: { name: 'Accept', value: 'application/vnd.example.v1+json' }) do
        devise_for :customers
      end
    end
  end

This is the json request with header Accept: application/vnd.example.v1+json

{
"customer": { "email": "...", "password": "..." } 
}