{"id":17924994,"url":"https://github.com/mwpastore/rack-session-smart_cookie","last_synced_at":"2025-03-24T03:30:58.495Z","repository":{"id":56890236,"uuid":"108713212","full_name":"mwpastore/rack-session-smart_cookie","owner":"mwpastore","description":"Slightly smarter session cookies for Rack 2 apps","archived":false,"fork":false,"pushed_at":"2018-09-06T20:44:09.000Z","size":25,"stargazers_count":43,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-19T02:44:16.097Z","etag":null,"topics":["cookies","rack","rack-middleware","ruby","rubygem"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mwpastore.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-29T07:12:56.000Z","updated_at":"2021-03-19T08:33:14.000Z","dependencies_parsed_at":"2022-08-21T00:50:30.069Z","dependency_job_id":null,"html_url":"https://github.com/mwpastore/rack-session-smart_cookie","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwpastore%2Frack-session-smart_cookie","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwpastore%2Frack-session-smart_cookie/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwpastore%2Frack-session-smart_cookie/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwpastore%2Frack-session-smart_cookie/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mwpastore","download_url":"https://codeload.github.com/mwpastore/rack-session-smart_cookie/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245204456,"owners_count":20577352,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cookies","rack","rack-middleware","ruby","rubygem"],"created_at":"2024-10-28T20:51:53.077Z","updated_at":"2025-03-24T03:30:58.233Z","avatar_url":"https://github.com/mwpastore.png","language":"Ruby","readme":"# Rack::Session::SmartCookie\n\n[![Gem Version](https://badge.fury.io/rb/rack-session-smart_cookie.svg)](https://badge.fury.io/rb/rack-session-smart_cookie)\n[![Build Status](https://travis-ci.org/mwpastore/rack-session-smart_cookie.svg?branch=master)](https://travis-ci.org/mwpastore/rack-session-smart_cookie)\n\nThe version of Rack::Session::Cookie that ships with Rack 2 has the following\nlimitations:\n\n* HMAC-SHA1 by default\n* Slow and/or bloated JSON, ZipJSON, or Marshal encoding out of the box\n* JSON encodings do not preserve Symbols\n* Digest is double-encoded and bloated (hexdigest of a base64)\n* Base64-encoded strings contain unecessary padding and characters that need to\n  be escaped (e.g. `/` becomes `%2F`), wasting precious cookie bytes\n* It has some bugs in the size check that may lead to dropped or truncated\n  cookies, token leakage, and/or cross-site request forgery\n\nOf course, none of these are true show-stoppers, and the worst can be worked\naround by passing e.g. `:hmac` and `:coder` to the initializer. But we are nice\npeople and we deserve nice things. This gem provides a minor derivative of\nRack::Session::Cookie with the following improvements:\n\n* HMAC-SHA256 by default\n* Compact binary serialization format (currently [MessagePack][3] but will\n  likely change to [CBOR][4] in the future) out of the box\n* Symbols are preserved with the default `:coder`\n* Digest is single-encoded and compact (base64 of a digest)\n* Base64-encoded strings are not padded and conform to URL-encoded form data\n  (e.g. `/` becomes `_`)\n* It does not perform a size check (use [Rack::Protection::MaximumCookie][2]\n  if you care about cookie limits)\n\nThe resultant cookies values with a small-to-medium sized session can be up to\n30% smaller in an apples-to-apples comparison (see below for examples).\n\n### Strategy\n\nThe main distinguishing feature of this cf. the stock implementation is that\nthe encoding (and decoding) step has been separated into two stages: 1. binary\nserialization and 2. stringification, instead of being combined into a single\n\"coder\" class. This allows the various cookie components to be either both\nserialized and stringified (in the case of the session payload) or merely\nstringified (in the case of the digest).\n\nThe other key realization is that the method Rack uses to escape cookie data\n([URI.encode_www_form_component][5]) will only ever allow non-padded, URL-safe\nBase64 plus period (`.`) and asterisk (`*`), so there's no sense in using any\nstringification scheme other than non-padded, URL-safe Base64! It doesn't need\nto be configurable. The serializer remains configurable as the `:coder`.\n\nThe remaining differences are mostly just better defaults: MessagePack and\nHMAC-SHA256.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'rack-session-smart_cookie'\n```\n\nAnd then execute:\n\n```console\n$ bundle\n```\n\nOr install it yourself as:\n\n```console\n$ gem install rack-session-smart_cookie\n```\n\n## Usage\n\n```ruby\nuse Rack::Session::SmartCookie\n```\n\nRack::Session::SmartCookie is a sub-class of [Rack::Session::Cookie][6] and\naccepts all the same options. If you choose to override the default `:coder`,\nit should *not* perform Base64 encoding or decoding.\n\nThe default `:coder` registers Symbol as a custom type on the factory. You can\neasily register additional custom types like so:\n\n```ruby\nmy_coder = Rack::Session::SmartCookie::MessagePack.new do |factory|\n  factory.register_type(0x00, MyCustomType) # 0x60..0xFF are reserved\nend\n\nuse Rack::Session::SmartCookie, :coder=\u003emy_coder\n```\n\nPlease see the [MessagePack][3] documentation for more details.\n\nRack::Session::SmartCookie also accepts `:digest` and `:digest_bytes` options\nthat allow you to choose the message digest algorithm and limit the size of the\ngenerated digest. This lets you e.g. truncate 64-byte HMAC-SHA512 digests down\nto 32 bytes (i.e. HMAC-SHA512/256):\n\n```\nuse Rack::Session::SmartCookie, :digest=\u003e'SHA512', :digest_bytes=\u003e32\n```\n\nThe `:hmac` option overrides the `:digest` option.\n\n## Comparisons\n\nFor general size and performance benchmarks of the encoding schemes, see\n[here][1]. Unfortunately, the post is slightly out-of-date and doesn't include\nZipJSON (Zlib+JSON) results. However, I was able to run the benchmarks locally\nand add ZipJSON. Although it comes in second-most compact at 289 bytes (cf.\nprotocol buffers and MessagePack at 204 and 373 bytes, respectively), it was\n97% slower to encode and 91% slower to decode cf. MessagePack.\n\nI put this mock session payload through the following configurations with\nHMAC-SHA256 and 128 sidbits and here are the results:\n\n```ruby\n{\n  :user_id=\u003e514,\n  :roles=\u003e[:user, :moderator, :mailbox],\n  :data=\u003e'{\"foo\":\"bar\",\"qux\":21}',\n  :issued_at=\u003eTime.now.to_f,\n  :valid_for=\u003e30*24*3_600\n}\n```\n\n### Rack::Session::Cookie w/ Base64::Marshal\n\n```\nBAh7C0kiD3Nlc3Npb25faWQGOgZFVEkiRTg3MzJkMTEzNDQyZjQyM2FlZGUy%0AMTdmNDY0OWEyOTk5\nMjkyYzg2M2JkNTFlY2VjYjY2ZDAzMTg0MTYzZWE3YTcG%0AOwBGSSIMdXNlcl9pZAY7AEZpAgICSSIK\ncm9sZXMGOwBGWwg6CXVzZXI6Dm1v%0AZGVyYXRvcjoMbWFpbGJveEkiCWRhdGEGOwBGSSIbeyJmb28i\nOiJiYXIiLCJx%0AdXgiOjIxfQY7AFRJIg5pc3N1ZWRfYXQGOwBGZhYxNTA5MjAzMDIzLjI3MzE2%0AN\nUkiDnZhbGlkX2ZvcgY7AEZpAwCNJw%3D%3D%0A--15aebb42ba0ff0a28436556c64eb2ef6d4dc7c6\na39e164eac0889052cec4f83f\n```\n\nSize: 420 bytes (100%)\n\nNote the percent-encoded characters and hex-encoded digest here and in the\nother Rack::Session::Cookie results.\n\n### Rack::Session::Cookie w/ Base64::JSON\n\n```\neyJzZXNzaW9uX2lkIjoiMTA4YzM1ZGIxMTFkNWZlMjk5NzUwMTc1Mzc2MzVm%0AMDJlZTIxMjM4ZmIx\nOTg2NDQ0ZTc4MTliY2RjZGQyYjc2YSIsInVzZXJfaWQi%0AOjUxNCwicm9sZXMiOlsidXNlciIsIm1v\nZGVyYXRvciIsIm1haWxib3giXSwi%0AZGF0YSI6IntcImZvb1wiOlwiYmFyXCIsXCJxdXhcIjoyMX0i\nLCJpc3N1ZWRf%0AYXQiOjE1MDkyMDI5NzEuODk3MzUyLCJ2YWxpZF9mb3IiOjI1OTIwMDB9%0A--7a6\n000bdece71118e768ccffedc645ace865b829536e335c304c00bb9050c625\n```\n\nSize: 377 bytes (90%)\n\n### Rack::Session::Cookie w/ Base64::ZipJSON\n\n```\neJwdjeGKwyAQhN9lf8uxGrcaX%2BU8wqa7gpCeXEyOQum7V%2FJvZj5m5gVde6%2Ft%0Ad6kCCcok1h\nbvwnqfJLpJ2VkpIXrxSmQZ76uzBb0qzYokSPY2E8aAXDQSg4Gz%0A636NkfUG9rZph%2FR9xYM%2Bmu\njOR7s0121tT%2FgxIHzwuH9lKK1lSBlW3jOYDH%2Fn%0Ac3hn36NQez9VFj4gWcLZoZsxfN1ioCkY%2\nBOetylLGdHI0IOL7A%2BnjQaI%3D%0A--fc193337b2900b6ce893143b5a52d36b55fafebc21cbde\n83712dce56bbf836f4\n```\n\nSize: 334 bytes (80%)\n\n### Rack::Session::SmartCookie w/ MessagePack\n\n```\nhqpzZXNzaW9uX2lk2UBiMGEzYzhlZTE4NzY3YjcwOTNmNThhN2E4MTI4NTNmNTlmNDYwOTgwMDA5NGY\n1Y2E4MTg5MjFjMjA4ZWQ1ZDY3p3VzZXJfaWTNAgKlcm9sZXOT1gB1c2VyxwkAbW9kZXJhdG9yxwcAbW\nFpbGJveKRkYXRhtnsiZm9vIjoiYmFyIiwicXV4IjoyMX2paXNzdWVkX2F0y0HWfSbUfbp0qXZhbGlkX\n2Zvcs4AJ40A.CRGTAgpN19Iz1plyX14kHmQYWTe0OtFbetqKZmCvSfg\n```\n\nSize: 292 bytes (70%)\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run\n`rake spec` to run the tests. You can also run `bin/console` for an interactive\nprompt that will allow you to experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To\nrelease a new version, update the version number in `version.rb`, and then run\n`bundle exec rake release`, which will create a git tag for the version, push\ngit commits and tags, and push the `.gem` file to\n[rubygems.org](https://rubygems.org).\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at\nhttps://github.com/mwpastore/rack-session-smart_cookie.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT\nLicense](http://opensource.org/licenses/MIT).\n\n[1]: https://gist.github.com/eirc/1300627\n[2]: https://github.com/mwpastore/rack-protection-maximum_cookie\n[3]: https://msgpack.org\n[4]: http://cbor.io\n[5]: https://ruby-doc.org/stdlib-2.4.2/libdoc/uri/rdoc/URI.html#method-c-encode_www_form_component\n[6]: http://www.rubydoc.info/gems/rack/Rack/Session/Cookie\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmwpastore%2Frack-session-smart_cookie","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmwpastore%2Frack-session-smart_cookie","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmwpastore%2Frack-session-smart_cookie/lists"}