devise-login-cookie 0.0.5 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/README.md +96 -25
- data/Rakefile +8 -0
- data/devise-login-cookie.gemspec +7 -3
- data/lib/devise-login-cookie.rb +1 -54
- data/lib/devise_login_cookie.rb +12 -0
- data/lib/devise_login_cookie/cookie.rb +81 -0
- data/lib/devise_login_cookie/strategy.rb +45 -0
- data/lib/{devise-login-cookie → devise_login_cookie}/version.rb +1 -1
- data/spec/cookie_spec.rb +109 -0
- data/spec/spec_helper.rb +52 -0
- data/spec/strategy_spec.rb +30 -0
- metadata +54 -6
data/README.md
CHANGED
@@ -1,39 +1,110 @@
|
|
1
1
|
devise-login-cookie
|
2
2
|
===================
|
3
3
|
|
4
|
-
|
4
|
+
A simple [Devise][1] extension for Single Sign On across same-domain web applications, using an [HMAC][2] signed login cookie. The cookie expiry is session-bound, and also contains a tamper-proof creation timestamp for server-enforced expiry.
|
5
|
+
|
6
|
+
[`OpenSSL::HMAC`][3] signing is performed by [`signed_json`][4] which also has implementations in PHP and Python, and can easily be implemented in other languages with OpenSSL and JSON. Note that standard Rails signed cookies are not appropriate for cross-platform use, as they use `Marshal.dump` internally.
|
7
|
+
|
8
|
+
[1]: https://github.com/plataformatec/devise
|
9
|
+
[2]: http://en.wikipedia.org/wiki/HMAC
|
10
|
+
[3]: http://ruby-doc.org/ruby-1.9/classes/OpenSSL/HMAC.html
|
11
|
+
[4]: https://github.com/pda/signed_json
|
5
12
|
|
6
13
|
|
7
14
|
Installation
|
8
15
|
------------
|
9
16
|
|
17
|
+
Simple:
|
18
|
+
|
10
19
|
gem install devise-login-cookie
|
11
20
|
|
21
|
+
Bundler-style:
|
22
|
+
|
12
23
|
echo 'gem "devise-login-cookie"' >> Gemfile
|
13
24
|
bundle install
|
14
25
|
|
15
|
-
|
16
|
-
require 'devise-login-cookie'
|
17
|
-
|
18
|
-
|
19
|
-
Information
|
20
|
-
-----------
|
21
|
-
|
22
|
-
While Devise sets a cookie for Remember Me logins, standard logins are only tracked in the session.
|
23
|
-
This extension sets a separate cookie upon authentication.
|
26
|
+
Rails:
|
24
27
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
28
|
+
# in config/initializers/devise.rb inside Devise.setup block
|
29
|
+
require 'devise-login-cookie'
|
30
|
+
config.warden do |manager|
|
31
|
+
manager.default_strategies(:scope => :user) << :devise_login_cookie
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
Background
|
36
|
+
----------
|
37
|
+
|
38
|
+
The `devise-login-cookie` extension was born from a web application composed of Rails, PHP and Django. Because the components were on the same domain, Single Sign On could be implemented with a simple shared cookie.
|
39
|
+
|
40
|
+
While Devise can set a cookie for Remember Me logins, standard logins are only tracked in the session. Also, Devise cookies and Rails session cookies are tied to Ruby due to their reliance on `Marshal.dump`.
|
41
|
+
|
42
|
+
This extension sets a separate cookie upon authentication, signed in a cross-platform manner, and deletes it via the `before_logout` Warden hook. For the `:user` scope, the cookie is named `login_user_token`, consistent with `remember_user_token` from Devise's `rememberable`. The same cookie, if valid, triggers authentication.
|
43
|
+
|
44
|
+
|
45
|
+
Development and Tests
|
46
|
+
---------------------
|
47
|
+
|
48
|
+
Patches are welcome; fork and send a pull request. Make sure the tests still work, and where possible, add to them. Let me know if you can't get the tests green to begin with.
|
49
|
+
|
50
|
+
RSpec 2 specifications cover the entire `Cookie` and part of the `Strategy`, but do not reach resource loading and authentication, nor cookie setting being triggered by login. These aspects need tobe tested in the host Rails application.
|
51
|
+
|
52
|
+
|
53
|
+
$ rake
|
54
|
+
|
55
|
+
DeviseLoginCookie::Cookie
|
56
|
+
#unset
|
57
|
+
deletes cookie
|
58
|
+
without any cookies
|
59
|
+
Cookie instance
|
60
|
+
should not be present
|
61
|
+
should not be valid
|
62
|
+
should not be set since 1970-01-01 10:00:00 +1000
|
63
|
+
#id
|
64
|
+
should be nil
|
65
|
+
#created_at
|
66
|
+
should be nil
|
67
|
+
#set
|
68
|
+
accepts resource
|
69
|
+
with an invalid cookie
|
70
|
+
Cookie instance
|
71
|
+
should be present
|
72
|
+
should not be valid
|
73
|
+
should not be set since 1970-01-01 10:00:00 +1000
|
74
|
+
#id
|
75
|
+
should be nil
|
76
|
+
#created_at
|
77
|
+
should be nil
|
78
|
+
#set
|
79
|
+
accepts resource
|
80
|
+
with a valid cookie
|
81
|
+
Cookie instance
|
82
|
+
should be present
|
83
|
+
should be valid
|
84
|
+
should not be set since 2010-12-08 23:46:30 +1100
|
85
|
+
should be set since 2010-12-08 23:46:29 +1100
|
86
|
+
should be set since 2010-12-08 23:46:28 +1100
|
87
|
+
#id
|
88
|
+
should == 5
|
89
|
+
#created_at
|
90
|
+
should == 2010-12-08 23:46:29 +1100
|
91
|
+
#set
|
92
|
+
accepts resource
|
93
|
+
|
94
|
+
DeviseLoginCookie::Strategy
|
95
|
+
#valid?
|
96
|
+
with no cookies
|
97
|
+
should not be valid
|
98
|
+
with invalid cookie
|
99
|
+
should not be valid
|
100
|
+
with valid cookie
|
101
|
+
should be valid
|
102
|
+
|
103
|
+
Finished in 0.06065 seconds
|
104
|
+
24 examples, 0 failures
|
105
|
+
|
106
|
+
|
107
|
+
Credits
|
108
|
+
-------
|
109
|
+
|
110
|
+
(c) 2010 Paul Annesley; MIT Licence.
|
data/Rakefile
CHANGED
data/devise-login-cookie.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "
|
3
|
+
require "devise_login_cookie/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "devise-login-cookie"
|
@@ -19,7 +19,11 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
|
-
s.add_dependency("signed_json")
|
23
|
-
s.
|
22
|
+
s.add_dependency("signed_json", ["~> 0.0.3"])
|
23
|
+
s.add_dependency("devise", ["~> 1.1"])
|
24
|
+
|
25
|
+
s.add_development_dependency("rspec", ["~> 2.2"])
|
26
|
+
s.add_development_dependency("rails") # devise requires this
|
27
|
+
s.add_development_dependency("rake")
|
24
28
|
|
25
29
|
end
|
data/lib/devise-login-cookie.rb
CHANGED
@@ -1,54 +1 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class Cookie
|
4
|
-
|
5
|
-
def initialize(warden, scope)
|
6
|
-
@scope = scope
|
7
|
-
@warden = warden
|
8
|
-
end
|
9
|
-
|
10
|
-
def set(user)
|
11
|
-
cookies[cookie_name] = cookie_options.merge(:value => cookie_value(user))
|
12
|
-
end
|
13
|
-
|
14
|
-
def unset
|
15
|
-
cookies.delete cookie_name, cookie_options
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def cookies
|
21
|
-
# .cookies provided by Devise in warden_compat.rb
|
22
|
-
# Roughly equivalent to: ActionDispatch::Request.new(env).cookie_jar
|
23
|
-
@warden.cookies
|
24
|
-
end
|
25
|
-
|
26
|
-
def cookie_name
|
27
|
-
"login_#{@scope}_token"
|
28
|
-
end
|
29
|
-
|
30
|
-
def cookie_value(user)
|
31
|
-
sign [ user.id, Time.now.to_i ]
|
32
|
-
end
|
33
|
-
|
34
|
-
def cookie_options
|
35
|
-
Rails.configuration.session_options.slice(:path, :domain, :secure, :httponly)
|
36
|
-
end
|
37
|
-
|
38
|
-
def sign(input)
|
39
|
-
require 'signed_json'
|
40
|
-
signer = SignedJson::Signer.new(Rails.configuration.secret_token)
|
41
|
-
signer.encode input
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
Warden::Manager.after_set_user do |user, warden, options|
|
47
|
-
Cookie.new(warden, options[:scope]).set(user)
|
48
|
-
end
|
49
|
-
|
50
|
-
Warden::Manager.before_logout do |user, warden, options|
|
51
|
-
Cookie.new(warden, options[:scope]).unset
|
52
|
-
end
|
53
|
-
|
54
|
-
end
|
1
|
+
require "devise_login_cookie"
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "devise_login_cookie/cookie"
|
2
|
+
require "devise_login_cookie/strategy"
|
3
|
+
|
4
|
+
Warden::Strategies.add(:devise_login_cookie, DeviseLoginCookie::Strategy)
|
5
|
+
|
6
|
+
Warden::Manager.after_set_user do |user, warden, options|
|
7
|
+
DeviseLoginCookie::Cookie.new(warden.cookies, options[:scope]).set(user)
|
8
|
+
end
|
9
|
+
|
10
|
+
Warden::Manager.before_logout do |user, warden, options|
|
11
|
+
DeviseLoginCookie::Cookie.new(warden.cookies, options[:scope]).unset
|
12
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "active_support/core_ext/hash/slice"
|
2
|
+
|
3
|
+
module DeviseLoginCookie
|
4
|
+
|
5
|
+
class Cookie
|
6
|
+
|
7
|
+
# for non-Rails test environment.
|
8
|
+
attr_writer :session_options
|
9
|
+
attr_accessor :secret_token
|
10
|
+
|
11
|
+
def initialize(cookies, scope)
|
12
|
+
@cookies = cookies
|
13
|
+
@scope = scope
|
14
|
+
end
|
15
|
+
|
16
|
+
# Sets the cookie, referencing the given resource.id (e.g. User)
|
17
|
+
def set(resource)
|
18
|
+
@cookies[cookie_name] = cookie_options.merge(:value => encoded_value(resource))
|
19
|
+
end
|
20
|
+
|
21
|
+
# Unsets the cookie via the HTTP response.
|
22
|
+
def unset
|
23
|
+
@cookies.delete cookie_name, cookie_options
|
24
|
+
end
|
25
|
+
|
26
|
+
# The id of the resource (e.g. User) referenced in the cookie.
|
27
|
+
def id
|
28
|
+
value[0]
|
29
|
+
end
|
30
|
+
|
31
|
+
# The Time at which the cookie was created.
|
32
|
+
def created_at
|
33
|
+
valid? ? Time.at(value[1]) : nil
|
34
|
+
end
|
35
|
+
|
36
|
+
# Whether the cookie appears valid.
|
37
|
+
def valid?
|
38
|
+
present? && value.all?
|
39
|
+
end
|
40
|
+
|
41
|
+
def present?
|
42
|
+
@cookies[cookie_name].present?
|
43
|
+
end
|
44
|
+
|
45
|
+
# Whether the cookie was set since the given Time
|
46
|
+
def set_since?(time)
|
47
|
+
created_at && created_at >= time
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def value
|
53
|
+
begin
|
54
|
+
@value = signer.decode @cookies[cookie_name]
|
55
|
+
rescue SignedJson::Error
|
56
|
+
[nil, nil]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def cookie_name
|
61
|
+
:"login_#{@scope}_token"
|
62
|
+
end
|
63
|
+
|
64
|
+
def encoded_value(resource)
|
65
|
+
signer.encode [ resource.id, Time.now.to_i ]
|
66
|
+
end
|
67
|
+
|
68
|
+
def cookie_options
|
69
|
+
@session_options ||= Rails.configuration.session_options
|
70
|
+
@session_options.slice(:path, :domain, :secure, :httponly)
|
71
|
+
end
|
72
|
+
|
73
|
+
def signer
|
74
|
+
require 'signed_json'
|
75
|
+
secret = secret_token || Rails.configuration.secret_token
|
76
|
+
@signer ||= SignedJson::Signer.new(secret)
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module DeviseLoginCookie
|
2
|
+
|
3
|
+
class Strategy < ::Devise::Strategies::Authenticatable
|
4
|
+
|
5
|
+
# TODO: configurable TTL
|
6
|
+
COOKIE_TTL = 86400 # one day
|
7
|
+
|
8
|
+
# for non-Rails test environment.
|
9
|
+
attr_accessor :secret_token
|
10
|
+
|
11
|
+
def valid?
|
12
|
+
cookie.valid?
|
13
|
+
end
|
14
|
+
|
15
|
+
def authenticate!
|
16
|
+
if fresh?(cookie) && validate(resource)
|
17
|
+
success!(resource)
|
18
|
+
else
|
19
|
+
pass
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def cookie
|
26
|
+
@cookie ||= Cookie.new(cookies, scope).tap do |cookie|
|
27
|
+
cookie.secret_token = secret_token if secret_token
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def fresh?(cookie)
|
32
|
+
cookie.set_since?(Time.now - COOKIE_TTL)
|
33
|
+
end
|
34
|
+
|
35
|
+
def resource
|
36
|
+
@resource ||= mapping.to.find(cookie.id)
|
37
|
+
end
|
38
|
+
|
39
|
+
def pass
|
40
|
+
cookie.unset
|
41
|
+
super
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
data/spec/cookie_spec.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module DeviseLoginCookie
|
4
|
+
|
5
|
+
describe Cookie do
|
6
|
+
|
7
|
+
include DeviseLoginCookie::SpecHelpers
|
8
|
+
|
9
|
+
describe "#unset" do
|
10
|
+
it "deletes cookie" do
|
11
|
+
options = { :path => "/a", :domain => "a.bc", :secure => true, :httponly => true }
|
12
|
+
jar = double().tap do |jar|
|
13
|
+
jar.should_receive(:delete).with(:login_test_token, options)
|
14
|
+
end
|
15
|
+
Cookie.new(jar, :test).tap{ |c| c.session_options = options }.unset
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "without any cookies" do
|
20
|
+
let(:cookie) { create_cookie }
|
21
|
+
subject { cookie }
|
22
|
+
|
23
|
+
describe "Cookie instance" do
|
24
|
+
it { should_not be_present }
|
25
|
+
it { should_not be_valid }
|
26
|
+
it { should_not be_set_since(Time.at(0)) }
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#id" do
|
30
|
+
subject { cookie.id }
|
31
|
+
it { should be_nil }
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#created_at" do
|
35
|
+
subject { cookie.created_at }
|
36
|
+
it { should be_nil }
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#set" do
|
40
|
+
it "accepts resource" do
|
41
|
+
cookie.set(resource(10))
|
42
|
+
cookie.id.should == 10
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "with an invalid cookie" do
|
48
|
+
let(:cookie) { create_cookie :login_test_token => "blarg" }
|
49
|
+
subject { cookie }
|
50
|
+
|
51
|
+
describe "Cookie instance" do
|
52
|
+
it { should be_present }
|
53
|
+
it { should_not be_valid }
|
54
|
+
it { should_not be_set_since(Time.at(0)) }
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#id" do
|
58
|
+
subject { cookie.id }
|
59
|
+
it { should be_nil }
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#created_at" do
|
63
|
+
subject { cookie.created_at }
|
64
|
+
it { should be_nil }
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "#set" do
|
68
|
+
it "accepts resource" do
|
69
|
+
cookie.set(resource(10))
|
70
|
+
cookie.id.should == 10
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "with a valid cookie" do
|
76
|
+
# force integer precision, rather than float.
|
77
|
+
let(:now) { Time.at(Time.now.to_i) }
|
78
|
+
let(:cookie) { create_valid_cookie(5, now) }
|
79
|
+
subject { cookie }
|
80
|
+
|
81
|
+
describe "Cookie instance" do
|
82
|
+
it { should be_present }
|
83
|
+
it { should be_valid }
|
84
|
+
it { should_not be_set_since(now + 1) }
|
85
|
+
it { should be_set_since(now) }
|
86
|
+
it { should be_set_since(now - 1) }
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "#id" do
|
90
|
+
subject { cookie.id }
|
91
|
+
it { should == 5 }
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "#created_at" do
|
95
|
+
subject { cookie.created_at }
|
96
|
+
it { should == now }
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "#set" do
|
100
|
+
it "accepts resource" do
|
101
|
+
cookie.set(resource(10))
|
102
|
+
cookie.id.should == 10
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require "rails"
|
2
|
+
require "devise"
|
3
|
+
require "devise_login_cookie"
|
4
|
+
require "action_dispatch/middleware/cookies"
|
5
|
+
|
6
|
+
module DeviseLoginCookie
|
7
|
+
|
8
|
+
module SpecHelpers
|
9
|
+
|
10
|
+
def resource(id)
|
11
|
+
require "ostruct"
|
12
|
+
OpenStruct.new(:id => id)
|
13
|
+
end
|
14
|
+
|
15
|
+
def cookie_jar(cookies = {})
|
16
|
+
ActionDispatch::Cookies::CookieJar.new.tap do |jar|
|
17
|
+
cookies.each { |key, value| jar[key] = value }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_cookie(cookies = {})
|
22
|
+
Cookie.new(cookie_jar(cookies), :test).tap do |cookie|
|
23
|
+
cookie.session_options = {}
|
24
|
+
cookie.secret_token = "secret"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_valid_cookie(id, created_at)
|
29
|
+
create_cookie :login_test_token => signed_cookie_value(id, created_at.to_i)
|
30
|
+
end
|
31
|
+
|
32
|
+
def signed_cookie_value(id, created_at)
|
33
|
+
# hacky shortcut better than re-implementing?
|
34
|
+
Cookie.new(nil, nil).tap do |cookie|
|
35
|
+
cookie.secret_token = "secret"
|
36
|
+
end.send(:signer).encode [id, created_at]
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_strategy(cookies = {})
|
40
|
+
env = { "action_dispatch.cookies" => cookie_jar(cookies) }
|
41
|
+
Strategy.new(env, :test).tap do |strategy|
|
42
|
+
strategy.secret_token = "secret"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def create_valid_strategy
|
47
|
+
create_strategy :login_test_token => signed_cookie_value(1, Time.now.to_i)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module DeviseLoginCookie
|
4
|
+
|
5
|
+
describe Strategy do
|
6
|
+
|
7
|
+
include DeviseLoginCookie::SpecHelpers
|
8
|
+
|
9
|
+
describe "#valid?" do
|
10
|
+
|
11
|
+
describe "with no cookies" do
|
12
|
+
subject { create_strategy }
|
13
|
+
it { should_not be_valid }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "with invalid cookie" do
|
17
|
+
subject { create_strategy(:login_test_token => "blarg") }
|
18
|
+
it { should_not be_valid }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "with valid cookie" do
|
22
|
+
subject { create_valid_strategy }
|
23
|
+
it { should be_valid }
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
+
- 1
|
7
8
|
- 0
|
8
|
-
|
9
|
-
version: 0.0.5
|
9
|
+
version: 0.1.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Paul Annesley
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-12-09 00:00:00 +11:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -23,11 +23,13 @@ dependencies:
|
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
24
|
none: false
|
25
25
|
requirements:
|
26
|
-
- -
|
26
|
+
- - ~>
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
segments:
|
29
29
|
- 0
|
30
|
-
|
30
|
+
- 0
|
31
|
+
- 3
|
32
|
+
version: 0.0.3
|
31
33
|
type: :runtime
|
32
34
|
version_requirements: *id001
|
33
35
|
- !ruby/object:Gem::Dependency
|
@@ -44,6 +46,46 @@ dependencies:
|
|
44
46
|
version: "1.1"
|
45
47
|
type: :runtime
|
46
48
|
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rspec
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ~>
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
segments:
|
58
|
+
- 2
|
59
|
+
- 2
|
60
|
+
version: "2.2"
|
61
|
+
type: :development
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: rails
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
type: :development
|
75
|
+
version_requirements: *id004
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: rake
|
78
|
+
prerelease: false
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
segments:
|
85
|
+
- 0
|
86
|
+
version: "0"
|
87
|
+
type: :development
|
88
|
+
version_requirements: *id005
|
47
89
|
description: Devise sets a "remember_token" cookie for Remember Me logins, but not for standard logins. This extension sets a separate cookie on login, which makes sharing login state between same-domain web applications easier.
|
48
90
|
email:
|
49
91
|
- paul@annesley.cc
|
@@ -60,7 +102,13 @@ files:
|
|
60
102
|
- Rakefile
|
61
103
|
- devise-login-cookie.gemspec
|
62
104
|
- lib/devise-login-cookie.rb
|
63
|
-
- lib/
|
105
|
+
- lib/devise_login_cookie.rb
|
106
|
+
- lib/devise_login_cookie/cookie.rb
|
107
|
+
- lib/devise_login_cookie/strategy.rb
|
108
|
+
- lib/devise_login_cookie/version.rb
|
109
|
+
- spec/cookie_spec.rb
|
110
|
+
- spec/spec_helper.rb
|
111
|
+
- spec/strategy_spec.rb
|
64
112
|
has_rdoc: true
|
65
113
|
homepage: http://rubygems.org/gems/devise-login-cookie
|
66
114
|
licenses: []
|