-
-
Notifications
You must be signed in to change notification settings - Fork 130
Configuring devise for APIs
In order for devise to know it can respond to json
format, you need to instruct the controller layer. Usually, you will add the following in ApplicationController
:
respond_to :json
If you are inheriting from ActionController::API
, first you will need to bring that functionality back:
include ActionController::MimeResponds
Overriding devise controllers should be the last option to consider. However, if this is necessary, some devise actions yield
the user in the crucial moment so that an override can call super
and just perform the needed action with it.
For example, if you need to override SessionsController
just to assign the user as an instance variable for the view, it is enough to do:
class MyApplicationSessionsController < Devise::SessionsController
def create
super { |resource| @resource = resource }
end
end
Then, don't forget in your routes:
devise_for :users, controllers: { sessions: 'my_application_sessions' }
If you want devise routes to use json
as default format (that is, you don't need to add .json
at the end of the URLs), use defaults
as the following:
devise_for :users, defaults: { format: :json }
Devise uses responders. In order to adjust validation errors coming from devise (for instance, during a sign up) to our application standards, we need to define and use a responder, which will need to implement the json_resource_errors
method. As it is included in the general responder, it has access to a resource
instance variable which in our case will contain the user with its errors. For instance:
module MyApplicationResponder
protected
def json_resource_errors
{
success: false,
errors: MyApplicationErrorFormatter.call(resource.errors)
}
end
end
Then, in the controller you have to use it:
responders :my_application
When an authentication fails, the execution path exits our application and lands into the default devise failure application. It is responsible to render the error message.
If we want to render with our own errors format standard, we should define and use a custom failure application. It is sufficient to just inherit from the devise one and overwrite the http_auth_body
method. From there, i18n_message
contains the error message.
For example:
class MyApplicationFailureApp < Devise::FailureApp
def http_auth_body
return super unless request_format == :json
{
sucess: false,
message: i18n_message
}.to_json
end
end
Now, in config/initializers/devise.rb
we need to config Warden (the engine on top of devise) to use it:
config.warden do |manager|
manager.failure_app = MyApplicationFailureApp
end