-
-
Notifications
You must be signed in to change notification settings - Fork 129
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 :jsonIf you are inheriting from ActionController::API, first you will need to bring that functionality back:
include ActionController::MimeRespondsOverriding 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
endThen, 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
endThen, in the controller you have to use it:
responders :my_applicationWhen 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
endNow, 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