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

前端 未结 3 1763
难免孤独
难免孤独 2020-12-04 04:55

My Rails app uses Devise for authentication. It has a sister iOS app, and users can log in to the iOS app using the same credentials that they use for the web app. So I need

3条回答
  •  半阙折子戏
    2020-12-04 05:17

    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]
      
      protected
      
      def set_csrf_header
         response.headers['X-CSRF-Token'] = form_authenticity_token
      end
      

      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 in
        NSString *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 object
        if (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  ->
        // create action called, token is reset
        // when login is successful, session and token are replaced 
        // and you can send authenticated requests
    

提交回复
热议问题