rack-session-smart_cookie 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +17 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +190 -0
- data/Rakefile +10 -0
- data/bin/console +7 -0
- data/bin/setup +6 -0
- data/lib/rack-session-smart_cookie.rb +2 -0
- data/lib/rack/session/smart_cookie.rb +163 -0
- data/lib/rack/session/smart_cookie/version.rb +16 -0
- data/rack-session-smart_cookie.gemspec +33 -0
- metadata +154 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4610e81040f4a6f234cc5365aca0fd89660e7985
|
4
|
+
data.tar.gz: 2d64b237c171b63c1b5791e9f1bf0e904c319e75
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5209a33d1cc7b7dbf542b0f3a0f016912877118208a4cc610533308521c62c572660490bee9d535e9e803c12935541dabe55b1be6b05dc23dc644741a3beef60
|
7
|
+
data.tar.gz: a80d1588a48494bef580385a852df4636b88377b3e9ee1d3ba11e40bc50b3922fe510741cb603f058b1d84270baf2c22816eb50237acc1cb1bd83d556a158de3
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
sudo: false
|
2
|
+
language: ruby
|
3
|
+
rvm:
|
4
|
+
- ruby-head
|
5
|
+
- 2.4.2
|
6
|
+
- 2.3.5
|
7
|
+
- 2.2.8
|
8
|
+
- jruby-head
|
9
|
+
- jruby-9.1.13.0
|
10
|
+
- jruby-9.0.5.0
|
11
|
+
env:
|
12
|
+
- RACK_VERSION='~> 2.0.0'
|
13
|
+
before_install: gem install bundler -v 1.15.4
|
14
|
+
matrix:
|
15
|
+
allow_failures:
|
16
|
+
- rvm: ruby-head
|
17
|
+
- rvm: jruby-head
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Mike Pastore
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
# Rack::Session::SmartCookie
|
2
|
+
|
3
|
+
The version of Rack::Session::Cookie that ships with Rack 2 has the following
|
4
|
+
limitations:
|
5
|
+
|
6
|
+
* Insecure SHA1 (HMAC-SHA1) by default
|
7
|
+
* Slow and/or bloated JSON, ZipJSON, or Marshal encoding out of the box
|
8
|
+
* JSON encodings do not preserve Symbols
|
9
|
+
* Digest is double-encoded and bloated (hexdigest of a base64)
|
10
|
+
* Base64-encoded strings contain unecessary padding and characters that need to
|
11
|
+
be escaped (e.g. `/` becomes `%2F`), wasting precious cookie bytes
|
12
|
+
* It has some bugs in the size check that may lead to truncated cookies, token
|
13
|
+
leakage, and/or cross-site request forgery
|
14
|
+
|
15
|
+
Of course, none of these are true show-stoppers, and the worst can be worked
|
16
|
+
around by passing e.g. `:hmac` and `:coder` to the initializer. But we are nice
|
17
|
+
people and we deserve nice things. This gem provides a minor derivative of
|
18
|
+
Rack::Session::Cookie with the following improvements:
|
19
|
+
|
20
|
+
* Secure SHA2 (HMAC-SHA-256) by default
|
21
|
+
* Compact binary serialization format (currently [MessagePack][3] but will
|
22
|
+
likely change to [CBOR][4] in the future) out of the box
|
23
|
+
* Symbols are preserved with the default `:coder`
|
24
|
+
* Digest is single-encoded and compact (base64 of a digest)
|
25
|
+
* Base64-encoded strings are not padded and conform to URL-encoded form data
|
26
|
+
(e.g. `/` becomes `_`)
|
27
|
+
* It does not perform a size check (use [Rack::Protection::MaximumCookie][2]
|
28
|
+
if you care about cookie limits)
|
29
|
+
|
30
|
+
The resultant cookies values with a small-to-medium sized session can be up to
|
31
|
+
30% smaller in an apples-to-apples comparison (see below for examples).
|
32
|
+
|
33
|
+
### Strategy
|
34
|
+
|
35
|
+
The main distinguishing feature of this cf. the stock implementation is that
|
36
|
+
the encoding (and decoding) step has been separated into two stages: 1. binary
|
37
|
+
serialization and 2. stringification, instead of being combined into a single
|
38
|
+
"coder" class. This allows the various cookie components to be either both
|
39
|
+
serialized and stringified (in the case of the session payload) or merely
|
40
|
+
stringified (in the case of the digest).
|
41
|
+
|
42
|
+
The other key realization is that the method Rack uses to escape cookie data
|
43
|
+
([URI.encode_www_form_component][5]) will only ever allow URL-safe Base64 plus
|
44
|
+
period (`.`) and asterisk (`*`), so there's no sense in using any
|
45
|
+
stringification scheme other than URL-safe Base64! It doesn't need to be
|
46
|
+
configurable. The serializer remains configurable as the `:coder`.
|
47
|
+
|
48
|
+
The remaining differences are mostly just better defaults: MessagePack and
|
49
|
+
SHA2.
|
50
|
+
|
51
|
+
## Installation
|
52
|
+
|
53
|
+
Add this line to your application's Gemfile:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
gem 'rack-session-smart_cookie'
|
57
|
+
```
|
58
|
+
|
59
|
+
And then execute:
|
60
|
+
|
61
|
+
```console
|
62
|
+
$ bundle
|
63
|
+
```
|
64
|
+
|
65
|
+
Or install it yourself as:
|
66
|
+
|
67
|
+
```console
|
68
|
+
$ gem install rack-session-smart_cookie
|
69
|
+
```
|
70
|
+
|
71
|
+
## Usage
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
use Rack::Session::SmartCookie
|
75
|
+
```
|
76
|
+
|
77
|
+
Rack::Session::SmartCookie accepts the same options as
|
78
|
+
[Rack::Session::Cookie][6]. If you choose to override the default `:coder`, it
|
79
|
+
should *not* perform the Base64 steps.
|
80
|
+
|
81
|
+
You can easily register additional custom types on the default coder's factory:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
my_coder = Rack::Session::SmartCookie::MessagePack.new
|
85
|
+
my_coder.factory.register_type(0x00, MyCustomType) # 0x60..0xFF are reserved
|
86
|
+
|
87
|
+
use Rack::Session::SmartCookie, :coder=>my_coder
|
88
|
+
```
|
89
|
+
|
90
|
+
## Comparisons
|
91
|
+
|
92
|
+
For general size and performance benchmarks of the encoding schemes, see
|
93
|
+
[here][1]. Unfortunately, the post is slightly out-of-date and doesn't include
|
94
|
+
ZipJSON (Zlib+JSON) results. However, I was able to run the benchmarks locally
|
95
|
+
and add ZipJSON. Although it comes in second-most compact at 289 bytes (cf.
|
96
|
+
protocol buffers and MessagePack at 204 and 373 bytes, respectively), it was
|
97
|
+
97% slower to encode and 91% slower to decode cf. MessagePack.
|
98
|
+
|
99
|
+
I put this mock session payload through the following configurations with SHA2
|
100
|
+
and 128 sidbits and here are the results:
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
{
|
104
|
+
:user_id=>514,
|
105
|
+
:roles=>[:user, :moderator, :mailbox],
|
106
|
+
:data=>'{"foo":"bar","qux":21}',
|
107
|
+
:issued_at=>Time.now.to_f,
|
108
|
+
:valid_for=>30*24*3_600
|
109
|
+
}
|
110
|
+
```
|
111
|
+
|
112
|
+
### Rack::Session::Cookie w/ Base64::Marshal
|
113
|
+
|
114
|
+
```
|
115
|
+
BAh7C0kiD3Nlc3Npb25faWQGOgZFVEkiRTg3MzJkMTEzNDQyZjQyM2FlZGUy%0AMTdmNDY0OWEyOTk5
|
116
|
+
MjkyYzg2M2JkNTFlY2VjYjY2ZDAzMTg0MTYzZWE3YTcG%0AOwBGSSIMdXNlcl9pZAY7AEZpAgICSSIK
|
117
|
+
cm9sZXMGOwBGWwg6CXVzZXI6Dm1v%0AZGVyYXRvcjoMbWFpbGJveEkiCWRhdGEGOwBGSSIbeyJmb28i
|
118
|
+
OiJiYXIiLCJx%0AdXgiOjIxfQY7AFRJIg5pc3N1ZWRfYXQGOwBGZhYxNTA5MjAzMDIzLjI3MzE2%0AN
|
119
|
+
UkiDnZhbGlkX2ZvcgY7AEZpAwCNJw%3D%3D%0A--15aebb42ba0ff0a28436556c64eb2ef6d4dc7c6
|
120
|
+
a39e164eac0889052cec4f83f
|
121
|
+
```
|
122
|
+
|
123
|
+
Size: 420 bytes (100%)
|
124
|
+
|
125
|
+
Note the percent-encoded characters and hex-encoded digest here and in the
|
126
|
+
other Rack::Session::Cookie results.
|
127
|
+
|
128
|
+
### Rack::Session::Cookie w/ Base64::JSON
|
129
|
+
|
130
|
+
```
|
131
|
+
eyJzZXNzaW9uX2lkIjoiMTA4YzM1ZGIxMTFkNWZlMjk5NzUwMTc1Mzc2MzVm%0AMDJlZTIxMjM4ZmIx
|
132
|
+
OTg2NDQ0ZTc4MTliY2RjZGQyYjc2YSIsInVzZXJfaWQi%0AOjUxNCwicm9sZXMiOlsidXNlciIsIm1v
|
133
|
+
ZGVyYXRvciIsIm1haWxib3giXSwi%0AZGF0YSI6IntcImZvb1wiOlwiYmFyXCIsXCJxdXhcIjoyMX0i
|
134
|
+
LCJpc3N1ZWRf%0AYXQiOjE1MDkyMDI5NzEuODk3MzUyLCJ2YWxpZF9mb3IiOjI1OTIwMDB9%0A--7a6
|
135
|
+
000bdece71118e768ccffedc645ace865b829536e335c304c00bb9050c625
|
136
|
+
```
|
137
|
+
|
138
|
+
Size: 377 bytes (90%)
|
139
|
+
|
140
|
+
### Rack::Session::Cookie w/ Base64::ZipJSON
|
141
|
+
|
142
|
+
```
|
143
|
+
eJwdjeGKwyAQhN9lf8uxGrcaX%2BU8wqa7gpCeXEyOQum7V%2FJvZj5m5gVde6%2Ft%0Ad6kCCcok1h
|
144
|
+
bvwnqfJLpJ2VkpIXrxSmQZ76uzBb0qzYokSPY2E8aAXDQSg4Gz%0A636NkfUG9rZph%2FR9xYM%2Bmu
|
145
|
+
jOR7s0121tT%2FgxIHzwuH9lKK1lSBlW3jOYDH%2Fn%0Ac3hn36NQez9VFj4gWcLZoZsxfN1ioCkY%2
|
146
|
+
BOetylLGdHI0IOL7A%2BnjQaI%3D%0A--fc193337b2900b6ce893143b5a52d36b55fafebc21cbde
|
147
|
+
83712dce56bbf836f4
|
148
|
+
```
|
149
|
+
|
150
|
+
Size: 334 bytes (80%)
|
151
|
+
|
152
|
+
### Rack::Session::SmartCookie w/ MessagePack
|
153
|
+
|
154
|
+
```
|
155
|
+
hqpzZXNzaW9uX2lk2UBiMGEzYzhlZTE4NzY3YjcwOTNmNThhN2E4MTI4NTNmNTlmNDYwOTgwMDA5NGY
|
156
|
+
1Y2E4MTg5MjFjMjA4ZWQ1ZDY3p3VzZXJfaWTNAgKlcm9sZXOT1gB1c2VyxwkAbW9kZXJhdG9yxwcAbW
|
157
|
+
FpbGJveKRkYXRhtnsiZm9vIjoiYmFyIiwicXV4IjoyMX2paXNzdWVkX2F0y0HWfSbUfbp0qXZhbGlkX
|
158
|
+
2Zvcs4AJ40A.CRGTAgpN19Iz1plyX14kHmQYWTe0OtFbetqKZmCvSfg
|
159
|
+
```
|
160
|
+
|
161
|
+
Size: 292 bytes (70%)
|
162
|
+
|
163
|
+
## Development
|
164
|
+
|
165
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
166
|
+
`rake spec` to run the tests. You can also run `bin/console` for an interactive
|
167
|
+
prompt that will allow you to experiment.
|
168
|
+
|
169
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
170
|
+
release a new version, update the version number in `version.rb`, and then run
|
171
|
+
`bundle exec rake release`, which will create a git tag for the version, push
|
172
|
+
git commits and tags, and push the `.gem` file to
|
173
|
+
[rubygems.org](https://rubygems.org).
|
174
|
+
|
175
|
+
## Contributing
|
176
|
+
|
177
|
+
Bug reports and pull requests are welcome on GitHub at
|
178
|
+
https://github.com/mwpastore/rack-session-smart_cookie.
|
179
|
+
|
180
|
+
## License
|
181
|
+
|
182
|
+
The gem is available as open source under the terms of the [MIT
|
183
|
+
License](http://opensource.org/licenses/MIT).
|
184
|
+
|
185
|
+
[1]: https://gist.github.com/eirc/1300627
|
186
|
+
[2]: https://github.com/mwpastore/rack-protection-maximum_cookie
|
187
|
+
[3]: https://msgpack.org
|
188
|
+
[4]: http://cbor.io
|
189
|
+
[5]: https://ruby-doc.org/stdlib-2.4.2/libdoc/uri/rdoc/URI.html#method-c-encode_www_form_component
|
190
|
+
[6]: http://www.rubydoc.info/gems/rack/Rack/Session/Cookie
|
data/Rakefile
ADDED
data/bin/console
ADDED
data/bin/setup
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'rack/session/smart_cookie/version'
|
3
|
+
|
4
|
+
require 'base64'
|
5
|
+
require 'msgpack'
|
6
|
+
require 'openssl'
|
7
|
+
require 'rack/session/cookie'
|
8
|
+
|
9
|
+
module Rack
|
10
|
+
module Session
|
11
|
+
class SmartCookie < Cookie
|
12
|
+
BAD_DIGESTS = %w[MD2 MD4 MD5 SHA SHA1].freeze
|
13
|
+
DEFAULT_DIGEST = 'SHA256'
|
14
|
+
SECRET_MIN_BYTESIZE = 16
|
15
|
+
|
16
|
+
class Base64
|
17
|
+
if ::Base64.respond_to?(:urlsafe_encode64) && ::Base64.method(:urlsafe_encode64).arity.abs >= 2
|
18
|
+
def self.encode(data)
|
19
|
+
::Base64.urlsafe_encode64(data, :padding=>false)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.decode(str)
|
23
|
+
return unless str
|
24
|
+
|
25
|
+
::Base64.urlsafe_decode64(str)
|
26
|
+
rescue
|
27
|
+
end
|
28
|
+
else
|
29
|
+
def self.encode(data)
|
30
|
+
::Base64.urlsafe_encode64(data).tap { |str| str.sub!(/=*\z/, '') }
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.decode(str)
|
34
|
+
return unless str
|
35
|
+
|
36
|
+
num_pad_chars =
|
37
|
+
case str.bytesize % 4
|
38
|
+
when 0 then 0
|
39
|
+
when 2 then 2
|
40
|
+
when 3 then 1
|
41
|
+
else
|
42
|
+
fail 'Invalid Base64-encoded string!'
|
43
|
+
end
|
44
|
+
|
45
|
+
::Base64.urlsafe_decode64(str + '=' * num_pad_chars)
|
46
|
+
rescue
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class MessagePack
|
52
|
+
attr_reader :factory
|
53
|
+
|
54
|
+
def initialize
|
55
|
+
# Create our own factory so we don't pollute the global namespace
|
56
|
+
# with our custom type.
|
57
|
+
@factory = ::MessagePack::Factory.new
|
58
|
+
# user gets 0x00...0x60
|
59
|
+
# we get 0x60...0x80
|
60
|
+
# MessagePack gets 0x80..0xFF
|
61
|
+
@factory.register_type(0x60, Symbol)
|
62
|
+
end
|
63
|
+
|
64
|
+
def encode(data)
|
65
|
+
# https://github.com/msgpack/msgpack-ruby/issues/141
|
66
|
+
factory.packer.write(data).to_str
|
67
|
+
end
|
68
|
+
|
69
|
+
def decode(bin)
|
70
|
+
return unless bin
|
71
|
+
|
72
|
+
# https://github.com/msgpack/msgpack-ruby/issues/141
|
73
|
+
factory.unpacker.feed(bin).read
|
74
|
+
rescue
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def initialize(app, options={})
|
79
|
+
options[:coder] ||= MessagePack.new
|
80
|
+
options[:hmac] = OpenSSL::Digest.const_get(DEFAULT_DIGEST) unless options.key?(:hmac)
|
81
|
+
|
82
|
+
super
|
83
|
+
|
84
|
+
if @secrets.any?
|
85
|
+
hmac = options[:hmac].new
|
86
|
+
|
87
|
+
warn <<-MSG if BAD_DIGESTS.include?(hmac.name)
|
88
|
+
SECURITY WARNING: You have elected to use an old and insecure message
|
89
|
+
digest algorithm (#{hmac.class}).
|
90
|
+
|
91
|
+
Such algorithms are generally considered to be effectively broken. It
|
92
|
+
is strongly recommended that you elect to use a message digest algorithm
|
93
|
+
from the SHA2 family: SHA224, SHA256, SHA384, or SHA512, or one of the
|
94
|
+
derivatives such as SHA512/256. This will help prevent exploits that
|
95
|
+
may be possible from crafted cookies.
|
96
|
+
|
97
|
+
Called from: #{caller[0]}.
|
98
|
+
MSG
|
99
|
+
|
100
|
+
unless (SECRET_MIN_BYTESIZE..hmac.block_length).cover?(@secrets.first.bytesize)
|
101
|
+
show_caveat = hmac.digest_length > SECRET_MIN_BYTESIZE
|
102
|
+
|
103
|
+
message = String.new(<<-MSG)
|
104
|
+
SECURITY WARNING: You have provided a session secret with a sub-optimal
|
105
|
+
byte size.
|
106
|
+
|
107
|
+
It is strongly recommended that you select a secret at least #{SECRET_MIN_BYTESIZE} bytes
|
108
|
+
long#{'*' if show_caveat}, but not longer than the block size (#{hmac.block_length} bytes) of the selected
|
109
|
+
message digest algorithm (#{hmac.class}). This will help
|
110
|
+
prevent exploits that may be possible from crafted cookies.
|
111
|
+
MSG
|
112
|
+
|
113
|
+
message << "\n " \
|
114
|
+
"* - Ideally, at least #{hmac.digest_length} bytes long.\n" if show_caveat
|
115
|
+
|
116
|
+
message << "\n " \
|
117
|
+
"Called from: #{caller[0]}."
|
118
|
+
|
119
|
+
warn message
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def unpacked_cookie_data(request)
|
127
|
+
request.fetch_header(RACK_SESSION_UNPACKED_COOKIE_DATA) do |k|
|
128
|
+
bin_session_data = nil
|
129
|
+
|
130
|
+
if (session_data = request.cookies[@key])
|
131
|
+
if @secrets.any?
|
132
|
+
if session_data =~ /\A([^.*]+)\.([^.*]+)\z/
|
133
|
+
session_data, digest = Regexp.last_match.captures
|
134
|
+
bin_session_data = Base64.decode(session_data)
|
135
|
+
bin_session_data = nil unless digest_match?(bin_session_data, digest)
|
136
|
+
end
|
137
|
+
else
|
138
|
+
bin_session_data = Base64.decode(session_data)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
request.set_header(k, coder.decode(bin_session_data) || {})
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def write_session(req, session_id, session, options)
|
147
|
+
session = session.merge('session_id'=>session_id)
|
148
|
+
bin_session_data = coder.encode(session)
|
149
|
+
session_data = Base64.encode(bin_session_data)
|
150
|
+
|
151
|
+
if @secrets.any?
|
152
|
+
session_data << '.' << generate_hmac(bin_session_data, @secrets.first)
|
153
|
+
end
|
154
|
+
|
155
|
+
session_data
|
156
|
+
end
|
157
|
+
|
158
|
+
def generate_hmac(data, secret)
|
159
|
+
Base64.encode(OpenSSL::HMAC.digest(@hmac.new, secret, data))
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
begin
|
3
|
+
require 'rack/session/cookie'
|
4
|
+
rescue LoadError
|
5
|
+
end
|
6
|
+
|
7
|
+
module Rack
|
8
|
+
module Session
|
9
|
+
# Stub out a parent class so gemspec can get the version from this file.
|
10
|
+
Cookie = Class.new unless defined?(Cookie)
|
11
|
+
|
12
|
+
class SmartCookie < Cookie
|
13
|
+
VERSION = '0.1.0'.freeze
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rack/session/smart_cookie/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'rack-session-smart_cookie'
|
8
|
+
spec.version = Rack::Session::SmartCookie::VERSION
|
9
|
+
spec.authors = ['Mike Pastore']
|
10
|
+
spec.email = ['mike@oobak.org']
|
11
|
+
|
12
|
+
spec.summary = %q{Slighty smarter session cookies for Rack apps}
|
13
|
+
spec.homepage = 'https://github.com/mwpastore/rack-session-smart_cookie#readme'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = %x{git ls-files -z}.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.bindir = 'exe'
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = %w[lib]
|
22
|
+
|
23
|
+
spec.required_ruby_version = '>= 2.2.8'
|
24
|
+
|
25
|
+
spec.add_dependency 'msgpack', '~> 1.1'
|
26
|
+
spec.add_dependency 'rack', ENV.fetch('RACK_VERSION', '~> 2.0.0')
|
27
|
+
|
28
|
+
spec.add_development_dependency 'bundler', '~> 1.15'
|
29
|
+
spec.add_development_dependency 'hobby', '~> 0.1.0'
|
30
|
+
spec.add_development_dependency 'minitest', '~> 5.0'
|
31
|
+
spec.add_development_dependency 'rack-test', '~> 0.7.0'
|
32
|
+
spec.add_development_dependency 'rake', '~> 12.0'
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-session-smart_cookie
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mike Pastore
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-11-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: msgpack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rack
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.15'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.15'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: hobby
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.1.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.1.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '5.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '5.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rack-test
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.7.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.7.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '12.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '12.0'
|
111
|
+
description:
|
112
|
+
email:
|
113
|
+
- mike@oobak.org
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".gitignore"
|
119
|
+
- ".travis.yml"
|
120
|
+
- Gemfile
|
121
|
+
- LICENSE.txt
|
122
|
+
- README.md
|
123
|
+
- Rakefile
|
124
|
+
- bin/console
|
125
|
+
- bin/setup
|
126
|
+
- lib/rack-session-smart_cookie.rb
|
127
|
+
- lib/rack/session/smart_cookie.rb
|
128
|
+
- lib/rack/session/smart_cookie/version.rb
|
129
|
+
- rack-session-smart_cookie.gemspec
|
130
|
+
homepage: https://github.com/mwpastore/rack-session-smart_cookie#readme
|
131
|
+
licenses:
|
132
|
+
- MIT
|
133
|
+
metadata: {}
|
134
|
+
post_install_message:
|
135
|
+
rdoc_options: []
|
136
|
+
require_paths:
|
137
|
+
- lib
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: 2.2.8
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
requirements: []
|
149
|
+
rubyforge_project:
|
150
|
+
rubygems_version: 2.6.13
|
151
|
+
signing_key:
|
152
|
+
specification_version: 4
|
153
|
+
summary: Slighty smarter session cookies for Rack apps
|
154
|
+
test_files: []
|