CookielessSessions
CookielessSessions implements a fallback mechanism for keeping Session-IDs (via GET-Parameter) on clients that doesn't support or allow cookies.
By default, the server sends a Set-Cookie header to the client. If the client supports and allows cookies, it will send back this Cookie header back in the next request. If not, then there won't be a Cookie header in the next requests from the client to the server and the server will initiate a new session for the client, in every request. In this case, sessions won't work.
This is what this gem was built for. There is only one other way to transfer a Session-ID between server and client: via GET-Paramters (and of course POST-Parameters).
Implementation
There isn't any magic in this gem. This gem consists of one module which implements a concern for controllers. The important method in this module is default_url_options and it only adds the session_key with the session_id to the options hash.
Rails uses the result of default_url_options method for Path / URL generation. Because of that, the session_key and session_id will be added to every Paths and URL generated in (cookieless_session enabled) controllers.
Requirements
An application based on Rails 4.x or 5.x configured with a session storage that supports the cookie_only: false option (e.g. redis-session-store).
Installation
Add this line to your application's Gemfile:
gem 'cookieless_sessions'
And then execute:
$ bundle
Or install it yourself as:
$ gem install cookieless_sessions
Usage
First, you need a cookie storage which supports the cookie_only option and turn it off. Rails built in session storages (cookie_store and active_record_store) doesn't support this option. That's why you need another cookie_storage. For example: this gem uses redis_session_store from the redis-session-store gem and a Redis database for its tests.
Include the module into the controller where you want to enable sessions via GET parameter:
class YourController < ApplicationController
include CookielessSessions::EnabledController
# ...
end
If you want to enable sessions via GET parameter for the whole application, include the module into your ApplicationController:
class ApplicationController < ActionController::Base
include CookielessSessions::EnabledController
# ...
end
If you want to disable sessions via GET parameter for a certain controller, you can do this by excepting the sessions_key from the default_url_options:
class OtherController < ApplicationController
def default_url_options
super.except(session_key)
end
end
Hint
If you want to overwrite default_url_options in one of your controllers that use cookieless_sessions and you want to keep that functionality, you should use super.dup and work on a copy:
class AnotherController < ApplicationController
def default_url_options
options ||= super.dup || {}
options[:foo] = :bar
return options
end
end
Security
There is one security impact: If you copy & paste a URL with your Sessions-ID to a friend and he has cookies disabled (this won't be happen if he has cookies enabled), he will get your session (e.g. he will be logged in with your account, depends on the application).
Two countermeasure could be to bind sessions to the client's IP-Address and add a session lifetime. For both you can use the frikandel gem. This should make it harder to steal and fix sessions.
Test
To run the test suite with different rails version by selecting the corresponding gemfile. You can use this one liners:
$ export BUNDLE_GEMFILE=Gemfile.rails-4.0.x && bundle update && bundle exec rake spec
$ export BUNDLE_GEMFILE=Gemfile.rails-4.1.x && bundle update && bundle exec rake spec
$ export BUNDLE_GEMFILE=Gemfile.rails-4.2.x && bundle update && bundle exec rake spec
$ export BUNDLE_GEMFILE=Gemfile.rails-5.0.x && bundle update && bundle exec rake spec
$ export BUNDLE_GEMFILE=Gemfile.rails-5.1.x && bundle update && bundle exec rake spec
$ export BUNDLE_GEMFILE=Gemfile.rails-5.2.x && bundle update && bundle exec rake spec
Changes
- v1.2.0 -- added support for rails-5.1
- v1.1.0 -- added support for rails-5.0; remove support for rails-3.2
- v1.0.1 -- added Rails32DestroyableSessionPatch: sets SID in options on destroy
- v1.0.0 -- first release with complete README; no code changes
- v0.0.2 -- improved and more flexible version with tests
- v0.0.1 -- initial and work-in-progress version without any tests
Contributing
- Fork it ( https://github.com/taktsoft/cookieless_sessions/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request