Reputation: 173
I have a RAILS API that integrates Devise and Doorkeeper. My POST request to registrations#create works but PUT/PATCH/DELETE results in "401 unauthorized" error. I suspect it might be some issue with authentication on Devise but that's where I'm stuck. Perhaps I am missing how to deal with current_user or skip_before_filters? I have tried a number of things like adding
skip_before_filter :verify_authenticity_token
skip_before_filter :authenticate_user!
Thank you!
routes.rb
require 'api_constraints'
Rails.application.routes.draw do
use_doorkeeper
devise_for :users, only: [:registrations, :passwords, :confirmations], controllers: {registrations: "api/registrations"}, defaults: { format: :json }
namespace :api, defaults: { format: :json }, constraints: { subdomain: 'api' }, path: '/' do
scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
get 'users/me', to: 'users#me'
end
end
end
rake routes
Prefix Verb URI Pattern Controller#Action
GET /oauth/authorize/:code(.:format) doorkeeper/authorizations#show
oauth_authorization GET /oauth/authorize(.:format) doorkeeper/authorizations#new
POST /oauth/authorize(.:format) doorkeeper/authorizations#create
DELETE /oauth/authorize(.:format) doorkeeper/authorizations#destroy
oauth_token POST /oauth/token(.:format) doorkeeper/tokens#create
oauth_revoke POST /oauth/revoke(.:format) doorkeeper/tokens#revoke
oauth_applications GET /oauth/applications(.:format) doorkeeper/applications#index
POST /oauth/applications(.:format) doorkeeper/applications#create
new_oauth_application GET /oauth/applications/new(.:format) doorkeeper/applications#new
edit_oauth_application GET /oauth/applications/:id/edit(.:format) doorkeeper/applications#edit
oauth_application GET /oauth/applications/:id(.:format) doorkeeper/applications#show
PATCH /oauth/applications/:id(.:format) doorkeeper/applications#update
PUT /oauth/applications/:id(.:format) doorkeeper/applications#update
DELETE /oauth/applications/:id(.:format) doorkeeper/applications#destroy
oauth_authorized_applications GET /oauth/authorized_applications(.:format) doorkeeper/authorized_applications#index
oauth_authorized_application DELETE /oauth/authorized_applications/:id(.:format) doorkeeper/authorized_applications#destroy
oauth_token_info GET /oauth/token/info(.:format) doorkeeper/token_info#show
user_password POST /users/password(.:format) devise/passwords#create {:format=>:json}
new_user_password GET /users/password/new(.:format) devise/passwords#new {:format=>:json}
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit {:format=>:json}
PATCH /users/password(.:format) devise/passwords#update {:format=>:json}
PUT /users/password(.:format) devise/passwords#update {:format=>:json}
cancel_user_registration GET /users/cancel(.:format) api/registrations#cancel {:format=>:json}
user_registration POST /users(.:format) api/registrations#create {:format=>:json}
new_user_registration GET /users/sign_up(.:format) api/registrations#new {:format=>:json}
edit_user_registration GET /users/edit(.:format) api/registrations#edit {:format=>:json}
PATCH /users(.:format) api/registrations#update {:format=>:json}
PUT /users(.:format) api/registrations#update {:format=>:json}
DELETE /users(.:format) api/registrations#destroy {:format=>:json}
user_confirmation POST /users/confirmation(.:format) devise/confirmations#create {:format=>:json}
new_user_confirmation GET /users/confirmation/new(.:format) devise/confirmations#new {:format=>:json}
GET /users/confirmation(.:format) devise/confirmations#show {:format=>:json}
api_users_me GET /users/me(.:format) api/v1/users#me {:format=>:json, :subdomain=>"api
registrations_controller.rb (that overrides Devise)
include ActionController::ImplicitRender
class Api::RegistrationsController < Devise::RegistrationsController
clear_respond_to
respond_to :json
respond_to :html, only: []
respond_to :xml, only: []
skip_before_filter :verify_authenticity_token
before_filter :not_allowed, only: [:new, :edit, :cancel]
def not_allowed
render json: {error: "Method Not Allowed"}, status: 405
end
private
def sign_up_params
params.require(:user).permit([
:email,
:password,
:password_confirmation,
:first_name,
:last_name,
])
end
def account_update_params
params.require(:user).permit([
:email,
:first_name,
:last_name,
:password,
:password_confirmation,
:current_password
])
end
end
Application.rb
class ApplicationController < ActionController::API
respond_to :json
before_filter :cors_preflight_check
after_filter :cors_set_access_control_headers
def cors_preflight_check
if request.method == 'OPTIONS'
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, DELETE, OPTIONS'
headers['Access-Control-Allow-Headers'] = 'X-Requested-With, X-Prototype-Version, Token'
headers['Access-Control-Max-Age'] = '1728000'
render text: '', content_type: 'text/plain'
end
end
def cors_set_access_control_headers
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, DELETE, OPTIONS'
headers['Access-Control-Allow-Headers'] = 'Origin, Content-Type, Accept, Authorization, Token'
headers['Access-Control-Max-Age'] = "1728000"
end
def current_resource_owner
User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
end
end
Upvotes: 2
Views: 2376
Reputation: 2328
You have selectively override Devise::RegistrationsController
methods, which are :new, :edit, :cancel
.
Rest methods are not defined in your class therefore they will be served by Devise::RegistrationsController
.
If you open devise source code, you will see :
class Devise::RegistrationsController < DeviseController
prepend_before_filter :require_no_authentication, only: [:new, :create, :cancel]
prepend_before_filter :authenticate_scope!, only: [:edit, :update, :destroy]
As you can see that :create
action does not require authentication therefore you don't see 401 for POST
request as it matches to create
action.
PUT/PATCH
matches to update
action which requires authentication, similarly DELETE
matches to 'destroy' action which also requires authentication therefore you are getting this 401 error.
To solve this issue, Add doorkeeper authorize for protected action after overriding actions in your RegistrationsController
.
Upvotes: 1