Use the built in option.

env['rack.session.options'][:skip] = true

or the equivalent

request.session_options[:skip] = true

You can find the documentation for it here https://github.com/rack/rack/blob/master/lib/rack/session/abstract/id.rb#L213


As is mentioned in a comment on John's answer, clearing the session will not prevent the session cookie from being sent. If you wish to totally remove the cookie from being sent, you have to use Rack middleware.

class CookieFilter
  def initialize(app)
    @app = app
  end

  def call(env)
    status, headers, body = @app.call(env)

    # use only one of the next two lines

    # this will remove ALL cookies from the response
    headers.delete 'Set-Cookie'
    # this will remove just your session cookie
    Rack::Utils.delete_cookie_header!(headers, '_app-name_session')

    [status, headers, body]
  end
end

Use it by creating an initializer with the following body:

Rails.application.config.middleware.insert_before ::ActionDispatch::Cookies, ::CookieFilter

To prevent the cookie filter to end up in application stack traces, which can be utterly confusing at times, you may want to silence it in the backtrace (Assuming you put it in lib/cookie_filter.rb):

Rails.backtrace_cleaner.add_silencer { |line| line.start_with? "lib/cookie_filter.rb" }

I'm not sure when they added it to Devise, but there appears to be a configuration that will let you disable the sending of the session cookie when using a auth_token:

# By default Devise will store the user in session. You can skip storage for
# :http_auth and :token_auth by adding those symbols to the array below.
# Notice that if you are skipping storage for all authentication paths, you
# may want to disable generating routes to Devise's sessions controller by
# passing :skip => :sessions to `devise_for` in your config/routes.rb
config.skip_session_storage = [:http_auth, :token_auth]

It does work well. The only issue I had was that I still needed to be able to make an initial request to my token_controller in order to generate/retrieve the token. I.e. POST /api/v1/tokens.json, which unfortunately would cause a session cookie to be returned for that request.

So I ended up implementing the CookieFilter intializer that Ryan Ahearn wrote above anyway.

Also, since my app has both a web front-end as well as a JSON api, I only wanted to filter the cookies for the JSON api. So I modified the CookieFilter class to first check the requests belonged to the api:

if env['PATH_INFO'].match(/^\/api/)
  Rack::Utils.delete_cookie_header!(headers, '_myapp_session')
end

Not sure if there's a better way of doing that...


Another solution: In the controller you want to avoid cookies, add this:

after_filter :skip_set_cookies_header

def skip_set_cookies_header
  request.session_options = {}
end

If you have a set of api controllers, set this in an api_controller class and let your other controllers inherit the api_controller.

This skips setting Set-Cookie header since the session opts is empty.