Rails-Devise-Warden Token Authentication + Android’s Volley

Hi, recently I’m trying to make an android app that uses a rails server. I used to code REST server before, but that is for javascript apps. Not android. And now that I’m trying to do so, I found a problem. Whenever the devise authenticate_user! failed and it throw 401 to the android app, Volley complain that some form of challenge key is missing. It work fine with a browser and it responded with an error in json form. This is the normal Devise behavior, which seems to also have support for api server. Because of the error in Volley, I can’t get the JSON that contain the error in order to show the message.

For the impatient one, the solution is this:

Devise::FailureApp #Autoload it

# Patch failure app so that the WWW-Authenticate message is sent regardless if using http_authenticatable.
class Devise::FailureApp < ActionController::Metal
  alias :old_http_auth :http_auth
  def http_auth
    self.headers["WWW-Authenticate"] = %(Basic realm=#{Devise.http_authentication_realm.inspect})

Put this in an initializer. Another thing is that, make sure that Volley tells Rails that it is accepting a json response, through HTTP Headers or ‘.json’ postfix.

The reason for the Volley error is that, when an HTTP server respond with HTTP 401, it is expected to respond with “WWW-Authenticate” header. The spec indicate that it MUST respond so. The problem is, the browser treat this header as an indicator to show user an HTTP Basic Authentication form, which is not always what we want. We just want to respond with 401 to indicate that the user is unauthorized for that particular resource. We can’t really use 403 because that means, Forbidden, a different meaning. Showing a 200 with an error message/json just feels too hackish for an api server. Because of this, devise did not send the header if the model did not enable http basic authentication.

By default, Devise sent out a 401 when it detect that the request is not of a ‘navigation’ format. By default that is [*,:html], which as far as I understand, every format and html. Or in another word, everything. For those of you who have problem with setting up Devise for an api server, change this to [:html] and make sure your client application properly indicate its accepted format. Using this, which basically means nothing else but the patch above, my api server seems to be working for now with no error on Volley (aside from authentication error, but that is expected). If the user manually send a request there from a browser, it will redirect to a login page.

Also, if you intend to use token authentication, checkout the devise-token_authentication gem. Devise developers for some reason (which seems to be security) removed the token authentication strategy from devise. This gem is a fork of the token authentication strategy.

This entry was posted in Programming, Projects. Bookmark the permalink.