Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: What does exception and null_session mean in protect_from_forgery

I'm trying to implement token-based API and saw these snippets by google

However, it's hard to understand the meaning by the literal meaning.

Any direction or basic knowledge about this, Thanks ~~

class ApplicationController < ActionController::Base

  protect_from_forgery with: :exception, if: Proc.new { |c| c.request.format != 'application/json' }
  protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' }
end
like image 323
user3675188 Avatar asked Feb 07 '23 05:02

user3675188


2 Answers

Rails's document about null_session is here http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ProtectionMethods/NullSession.html#method-i-handle_unverified_request, if you check the source code of it's handle_unverified_request method:

def handle_unverified_request
  request = @controller.request
  request.session = NullSessionHash.new(request.env)
  request.env['action_dispatch.request.flash_hash'] = nil
  request.env['rack.session.options'] = { skip: true }
  request.env['action_dispatch.cookies'] = NullCookieJar.build(request)
end

that means if the request dose't get through the verify_authenticity_token ,then rails will not fetch the session by cookie data, but create a new session for this request. And that session is a instance of NullSessionHash, so "null_session".

like image 141
lei liu Avatar answered May 13 '23 21:05

lei liu


I had this concern when working on a Rails 6 API only application.

By default, Rails applies Cross-Site Request Forgery (CSRF) protection to all controllers that subclass from ApplicationController using the following line:

protect_from_forgery with: :exception

But are there instances where you’d want to respond differently, or even ignore CSRF protection altogether? The answer, of course, is “yes”.

If your project or a portion of your project uses an alternative method for authentication such as API tokens or any other “stateless” authentication, then you can safely remove the protect_from_forgery line from whatever base class those controllers inherit.

On the other hand, if your project uses stateful authentication and APIs, such as those projects with lots of AJAX requests, it can be advantageous to use :null_session with protect_from_forgery like so:

protect_from_forgery with: :null_session

That means the user won’t be logged in anymore for that action and can’t perform the change (if the action requires a signed-in user). However, after the action, the session values will be back and the session ID will be the same, so the user will be logged in.

Rather than throwing an exception, which your JavaScript may not be able to handle, it instead sets the session value to nil for the duration of the action. By doing this, any authorization or action scoped to the current user will result in errors that your JavaScript can more easily work with.

So, if you're working on a Rails API only application, you can use this to protect against Cross-Site Request Forgery (CSRF) attacks. This suffices for both cases when either of them arises:

class ApplicationController < ActionController::API
  include ActionController::RequestForgeryProtection

  if Proc.new { |c| c.request.format != 'application/json' }
    protect_from_forgery with: :exception
  end
    
  if Proc.new { |c| c.request.format == 'application/json' }
    protect_from_forgery with: :null_session
  end
end

This implements protect_from_forgery with: :exception when your requests are not of the application/json format, and protect_from_forgery with: :null_session when your requests are of the application/json format.

Note: protect_from_forgery is a class method included in ActionController::RequestForgeryProtection, which is why include ActionController::RequestForgeryProtection was included.

Resources:

  1. CSRF Protection and Ruby on Rails
  2. Undefined method protect_from_forgery for Clearance::SessionsController:Class

That's all.

I hope this helps

like image 40
Promise Preston Avatar answered May 13 '23 20:05

Promise Preston