Is this Rails JSON authentication API (using Devise) secure? Is this Rails JSON authentication API (using Devise) secure? json json

Is this Rails JSON authentication API (using Devise) secure?


You don't want to disable CSRF, I have read that people think it doesn't apply to JSON APIs for some reason, but this is a misunderstanding. To keep it enabled, you want to make a few changes:

  • on there server side add a after_filter to your sessions controller:

    after_filter :set_csrf_header, only: [:new, :create]protecteddef set_csrf_header   response.headers['X-CSRF-Token'] = form_authenticity_tokenend

    This will generate a token, put it in your session and copy it in the response header for selected actions.

  • client side (iOS) you need to make sure two things are in place.

    • your client needs to scan all server responses for this header and retain it when it is passed along.

      ... get ahold of response object// response may be a NSURLResponse object, so convert:NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;// grab token if present, make sure you have a config object to store it inNSString *token = [[httpResponse allHeaderFields] objectForKey:@"X-CSRF-Token"];if (token)   [yourConfig setCsrfToken:token];
    • finally, your client needs to add this token to all 'non GET' requests it sends out:

      ... get ahold of your request objectif (yourConfig.csrfToken && ![request.httpMethod isEqualToString:@"GET"])  [request setValue:yourConfig.csrfToken forHTTPHeaderField:@"X-CSRF-Token"];

Final piece of the puzzle is to understand that when logging in to devise, two subsequent sessions/csrf tokens are being used. A login flow would look like this:

GET /users/sign_in ->  // new action is called, initial token is set  // now send login form on callback:  POST /users/sign_in <username, password> ->    // create action called, token is reset    // when login is successful, session and token are replaced     // and you can send authenticated requests


Your example seems to mimic the code from the Devise blog - https://gist.github.com/josevalim/fb706b1e933ef01e4fb6

As mentioned in that post, you are doing it similar to option 1, which they say is the insecure option. I think the key is that you don't want to simply reset the authentication token every time the user is saved. I think the token should be created explicitly (by some kind of TokenController in the API) and should expire periodically.

You'll notice I say 'I think' since (as far as I can tell) nobody has any more information on this.


The top 10 most common vulnerablites in web applications are documented in the OWASP Top 10. This question mentioned that Cross-Site Request Forgery(CSRF) protection was disabled, and CSRF is on the OWASDP Top 10. In short, CSRF is used by attackers to perform actions as an authenticated user. Disabling CSRF protection will lead to high risk vulnerabilities in an application, and undermines the purpose of having a secure authentication system. Its likely that the CSRF protection was failing, because the client is failing to pass the CSRF synchronization token.

Read the entire OWASP top 10, failing to do so is extremely hazardous. Pay close attention to Broken Authentication and Session Management, also check out the Session Management Cheat Sheet.