RailsCompatibleCookiesUtils - Utility methods to deal with cookies managed by a Rails app
This is a Ruby-only (2.0 or later) implementation of utility methods to manage cookies
generated by a Rails app. It doesn't depend on any external gems.
Just tell RailsCompatibleCookiesUtils the Rails app secret key and it will be able to handle
signed and encrypted cookies (it can both read and write those values).
This is useful if you intend to share your cookies (or session) among different Ruby web
applications (they could be even running in the same domain behind a proxy for example) when
at least one of the applications is not a Rails one.
Or you could use this if you are switching from Rails to another Ruby web framework and want
to deal with old valid sessions after deploying (either if it's a temporary strategy or you
want to keep this encrypting and signing algorithms permanently).
Installation
Add this line to your application's Gemfile:
gem 'rails_compatible_cookies_utils'
And then execute:
$ bundle
Or install it yourself as:
$ gem install rails_compatible_cookies_utils
Usage
You may test the following examples in a REPL with bin/console
.
Initialization
Creating an instance using the default serializer in Rails 5 generated applications (JSON):
cookies_utils = RailsCompatibleCookiesUtils.new 'secret_key_base'
Usually you'll pass the Rails app secret_key_base
(Rails.application.config.secret_key_base
)
you want to share cookies with. You can also generate a Rails-like random secret key for other
purposes if you want:
secret_key_base = SecureRandom.hex 64
In previous Rails releases the default serializer was Marshal. If your app uses it, initialize
it this way:
cookies_utils = RailsCompatibleCookiesUtils.new 'secret_key_base', serializer: Marshal
Thread-safety
An instance of RailsCompatibleCookiesUtils is not thread-safe, so ensure to create a new
instance for each thread using such an instance or make the calls in within a mutex synchronized
block.
Read an encrypted cookie value
This would be the equivalent of cookies.encrypted['_myapp_session']
:
raw_cookie_string = env['HTTP_COOKIE']
cookies_utils.decrypt_cookie_key raw_cookie_string, '_myapp_session'
Or if you already have the parsed and unescaped cookie value:
value = cookies_utils.cookies(env['HTTP_COOKIE'])['_myapp_session']
cookies_utils.decrypt value
Write an encrypted value to the cookies
require 'cgi'
value = { test: true }
cookie = CGI::Cookie.new 'some_key', cookies_utils.encrypt value
cookies_utils.decrypt(cookies_utils.encrypt 'secret') == 'secret'
Signed only values
Rails also allows you to just sign a cookie value without encrypting it
(cookies.signed['key'] = 'value'
). To verify and decode the value:
cookies_utils.signed_cookie_key env['HTTP_COOKIE'], 'some_key'
Serialize and sign a cookie value with:
require 'cgi'
value = { test: true }
cookie = CGI::Cookie.new 'some_key', cookies_utils.serialize_and_sign value
cookies_utils.verify_and_deserialize(cookies_utils.serialize_and_sign 'secret') == 'secret'
Invalid values handling
If the value is invalid decrypt_cookie_key
, decrypt
, signed_cookie_key
,
verify_and_deserialize
and serialize_and_sign
will all return nil. All of
them have a bang variant which will raise RailsCompatibleCookiesUtils::InvalidSignature
instead in those cases (like decrypt!
).
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub.
License
The gem is available as open source under the terms of the MIT License.