active_record_openid_store 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/README.rdoc +49 -0
- data/Rakefile +1 -0
- data/active_record_openid_store.gemspec +26 -0
- data/app/models/active_record_openid_store/association.rb +10 -0
- data/app/models/active_record_openid_store/nonce.rb +3 -0
- data/lib/active_record_openid_store.rb +14 -0
- data/lib/active_record_openid_store/active_record_store.rb +58 -0
- data/lib/active_record_openid_store/engine.rb +14 -0
- data/lib/active_record_openid_store/railties/tasks.rake +7 -0
- data/lib/active_record_openid_store/version.rb +3 -0
- data/lib/generators/active_record_openid_store/USAGE +6 -0
- data/lib/generators/active_record_openid_store/active_record_openid_store_generator.rb +24 -0
- data/lib/generators/active_record_openid_store/templates/migration.rb +27 -0
- data/spec/spec_helper.rb +19 -0
- data/test/store_test.rb +212 -0
- data/todos.txt +5 -0
- metadata +120 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.2@active_record_openid_store
|
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
=ActiveRecord Based OpenID Store
|
2
|
+
|
3
|
+
A store is required by an OpenID server and optionally by the consumer to store associations, nonces, and auth key information across requests and processes. If rails is distributed across several machines, they must must all have access to the same OpenID store data, so the FilesystemStore won't do.
|
4
|
+
|
5
|
+
This directory contains a plugin for connecting your OpenID enabled rails app to an ActiveRecord based OpenID store. <b>The code here is copied from the {openid-ruby library}[https://github.com/openid/ruby-openid] examples (https://github.com/openid/ruby-openid/tree/master/examples/active_record_openid_store)</b>. All I did was move some things around, add a namespace and package it all up as a rails engine/plugin, with some conveniences, for use with Rails 3.
|
6
|
+
|
7
|
+
==Usage
|
8
|
+
|
9
|
+
Just add it as a gem in your Gemfile
|
10
|
+
|
11
|
+
<tt>gem 'active_record_openid_store'</tt>
|
12
|
+
|
13
|
+
You will now have access to a rails generator to create the necessary migrations. Simply run:
|
14
|
+
|
15
|
+
<tt>rails g active_record_openid_store</tt>
|
16
|
+
|
17
|
+
Now that we have the migration we can create the necessary tables:
|
18
|
+
|
19
|
+
<tt>rake db:migrate</tt>
|
20
|
+
|
21
|
+
You should now have two extra tables, +open_id_associations+ and +open_id_nonces+.
|
22
|
+
|
23
|
+
At this stage you're essentially good to go, you can create a new store like this:
|
24
|
+
|
25
|
+
<tt>ActiveRecordOpenidStore::ActiveRecordStore.new</tt>
|
26
|
+
|
27
|
+
You can do this anywhere in your Rails app.
|
28
|
+
|
29
|
+
==What about garbage collection?
|
30
|
+
|
31
|
+
Adding the +active_record_openid_store+ gem to your Gemfile also gives you access to the <tt>openid:gc</tt> rake task. You may use this task at any time to clean up any expired nonces and associations.
|
32
|
+
|
33
|
+
<tt>rake openid:gc</tt>
|
34
|
+
|
35
|
+
This task isn't doing anything fancy under the hood, it simply calls the cleanup method of the active record store (i.e.: <tt>ActiveRecordOpenidStore::ActiveRecordStore.new.cleanup</tt>)
|
36
|
+
|
37
|
+
==Example With Omniauth
|
38
|
+
|
39
|
+
Let's say you're using omniauth[https://github.com/intridea/omniauth] and you're also using Google OpenID to authenticate your users. You want to configure Google OpenID to use the ActiveRecord OpenID store. Given that you've followed the instructions above to add the gem and create the tables, you would configure Google OpenID like this.
|
40
|
+
|
41
|
+
In your <tt>config/initializers/omniauth.rb</tt>:
|
42
|
+
|
43
|
+
|
44
|
+
Rails.application.config.middleware.use OmniAuth::Builder do
|
45
|
+
provider :openid, ActiveRecordOpenidStore::ActiveRecordStore.new, :name => 'google', :identifier => 'https://www.google.com/accounts/o8/id'
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
Having done this, if you go to +/auth/google+ (as per how omniauth works) you will find that your associations and nonces are being stored in the database. Sweet!
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "active_record_openid_store/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "active_record_openid_store"
|
7
|
+
s.version = ActiveRecordOpenidStore::VERSION
|
8
|
+
s.authors = ["Alan Skorkin"]
|
9
|
+
s.email = ["alan@skorks.com"]
|
10
|
+
s.homepage = "https://github.com/skorks/active_record_openid_store"
|
11
|
+
s.summary = %q{An Active Record-based OpenID store}
|
12
|
+
s.description = %q{A store is required by an OpenID server and optionally by the consumer to store associations, nonces, and auth key information across requests and processes. If rails is distributed across several machines, they must must all have access to the same OpenID store data, so the FilesystemStore won't do. The code here is copied from the openid-ruby library examples. All I did was move some things around, add a namespace and package it all up as a rails engine/plugin, with some conveniences, for use with Rails 3.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "active_record_openid_store"
|
15
|
+
|
16
|
+
s.add_dependency 'ruby-openid', '~> 2.1.0'
|
17
|
+
|
18
|
+
s.add_development_dependency 'rake'
|
19
|
+
s.add_development_dependency 'rspec', '~> 2.5.0'
|
20
|
+
s.add_development_dependency 'json', '~> 1.4.3' # multi_json implementation
|
21
|
+
|
22
|
+
s.files = `git ls-files`.split("\n")
|
23
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
25
|
+
s.require_paths = ["lib"]
|
26
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'openid/association'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
class ActiveRecordOpenidStore::Association < ActiveRecord::Base
|
5
|
+
set_table_name 'open_id_associations'
|
6
|
+
def from_record
|
7
|
+
OpenID::Association.new(handle, secret, Time.at(issued), lifetime, assoc_type)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "active_record_openid_store/version"
|
2
|
+
|
3
|
+
module ActiveRecordOpenidStore
|
4
|
+
if defined?(Rails)
|
5
|
+
require 'active_record_openid_store/engine'
|
6
|
+
else
|
7
|
+
models_dir = Pathname.new(File.expand_path(File.dirname(__FILE__))).join("../app/models").to_s
|
8
|
+
lib_dir = File.expand_path(File.dirname(__FILE__))
|
9
|
+
$:.unshift(models_dir) unless $:.include?(models_dir)
|
10
|
+
$:.unshift(lib_dir) unless $:.include?(lib_dir)
|
11
|
+
require 'active_record_openid_store/active_record_store'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'openid'
|
2
|
+
require 'openid/store/interface'
|
3
|
+
require 'active_record_openid_store/association'
|
4
|
+
require 'active_record_openid_store/nonce'
|
5
|
+
|
6
|
+
module ActiveRecordOpenidStore
|
7
|
+
class ActiveRecordStore < OpenID::Store::Interface
|
8
|
+
def store_association(server_url, assoc)
|
9
|
+
remove_association(server_url, assoc.handle)
|
10
|
+
ActiveRecordOpenidStore::Association.create!(:server_url => server_url,
|
11
|
+
:handle => assoc.handle,
|
12
|
+
:secret => assoc.secret,
|
13
|
+
:issued => assoc.issued.to_i,
|
14
|
+
:lifetime => assoc.lifetime,
|
15
|
+
:assoc_type => assoc.assoc_type)
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_association(server_url, handle=nil)
|
19
|
+
assocs = if handle.blank?
|
20
|
+
ActiveRecordOpenidStore::Association.find_all_by_server_url(server_url)
|
21
|
+
else
|
22
|
+
ActiveRecordOpenidStore::Association.find_all_by_server_url_and_handle(server_url, handle)
|
23
|
+
end
|
24
|
+
|
25
|
+
assocs.reverse.each do |assoc|
|
26
|
+
a = assoc.from_record
|
27
|
+
if a.expires_in == 0
|
28
|
+
assoc.destroy
|
29
|
+
else
|
30
|
+
return a
|
31
|
+
end
|
32
|
+
end if assocs.any?
|
33
|
+
|
34
|
+
return nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def remove_association(server_url, handle)
|
38
|
+
ActiveRecordOpenidStore::Association.delete_all(['server_url = ? AND handle = ?', server_url, handle]) > 0
|
39
|
+
end
|
40
|
+
|
41
|
+
def use_nonce(server_url, timestamp, salt)
|
42
|
+
return false if ActiveRecordOpenidStore::Nonce.find_by_server_url_and_timestamp_and_salt(server_url, timestamp, salt)
|
43
|
+
return false if (timestamp - Time.now.to_i).abs > OpenID::Nonce.skew
|
44
|
+
ActiveRecordOpenidStore::Nonce.create!(:server_url => server_url, :timestamp => timestamp, :salt => salt)
|
45
|
+
return true
|
46
|
+
end
|
47
|
+
|
48
|
+
def cleanup_nonces
|
49
|
+
now = Time.now.to_i
|
50
|
+
ActiveRecordOpenidStore::Nonce.delete_all(["timestamp > ? OR timestamp < ?", now + OpenID::Nonce.skew, now - OpenID::Nonce.skew])
|
51
|
+
end
|
52
|
+
|
53
|
+
def cleanup_associations
|
54
|
+
now = Time.now.to_i
|
55
|
+
ActiveRecordOpenidStore::Association.delete_all(['issued + lifetime > ?',now])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "active_record_openid_store"
|
2
|
+
require "rails"
|
3
|
+
|
4
|
+
module ActiveRecordOpenidStore
|
5
|
+
class Engine < Rails::Engine
|
6
|
+
#engine_name :active_record_openid_store
|
7
|
+
initializer "active_record_openid_store init" do |app|
|
8
|
+
require 'active_record_openid_store/active_record_store'
|
9
|
+
end
|
10
|
+
rake_tasks do
|
11
|
+
load "active_record_openid_store/railties/tasks.rake"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
|
4
|
+
class ActiveRecordOpenidStoreGenerator < Rails::Generators::Base
|
5
|
+
include Rails::Generators::Migration
|
6
|
+
|
7
|
+
desc "Create the tables necessary for an ActiveRecord OpenID store"
|
8
|
+
|
9
|
+
def self.source_root
|
10
|
+
@source_root ||= File.join(File.dirname(__FILE__), 'templates')
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.next_migration_number(dirname)
|
14
|
+
if ActiveRecord::Base.timestamped_migrations
|
15
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
16
|
+
else
|
17
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_migration_file
|
22
|
+
migration_template 'migration.rb', 'db/migrate/create_active_record_openid_store_tables.rb'
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class CreateActiveRecordOpenidStoreTables < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :open_id_associations do |t|
|
4
|
+
t.binary :server_url, :null => false
|
5
|
+
t.string :handle, :null => false
|
6
|
+
t.binary :secret, :null => false
|
7
|
+
t.integer :issued, :null => false
|
8
|
+
t.integer :lifetime, :null => false
|
9
|
+
t.string :assoc_type, :null => false
|
10
|
+
|
11
|
+
t.timestamps
|
12
|
+
end
|
13
|
+
|
14
|
+
create_table :open_id_nonces do |t|
|
15
|
+
t.string :server_url, :null => false
|
16
|
+
t.integer :timestamp, :null => false
|
17
|
+
t.string :salt, :null => false
|
18
|
+
|
19
|
+
t.timestamps
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.down
|
24
|
+
drop_table :open_id_associations
|
25
|
+
drop_table :open_id_nonces
|
26
|
+
end
|
27
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
begin
|
4
|
+
require 'rubygems'
|
5
|
+
rescue LoadError
|
6
|
+
nil
|
7
|
+
end
|
8
|
+
require 'bundler'
|
9
|
+
Bundler.setup
|
10
|
+
require 'rspec'
|
11
|
+
require 'active_record_openid_store'
|
12
|
+
|
13
|
+
# Requires supporting files with custom matchers and macros, etc,
|
14
|
+
# in ./support/ and its subdirectories.
|
15
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
16
|
+
|
17
|
+
RSpec.configure do |config|
|
18
|
+
|
19
|
+
end
|
data/test/store_test.rb
ADDED
@@ -0,0 +1,212 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
|
+
require 'test/unit'
|
3
|
+
RAILS_ENV = "test"
|
4
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../../../../config/environment.rb'))
|
5
|
+
|
6
|
+
module StoreTestCase
|
7
|
+
@@allowed_handle = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
|
8
|
+
@@allowed_nonce = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
9
|
+
|
10
|
+
def _gen_nonce
|
11
|
+
OpenID::CryptUtil.random_string(8, @@allowed_nonce)
|
12
|
+
end
|
13
|
+
|
14
|
+
def _gen_handle(n)
|
15
|
+
OpenID::CryptUtil.random_string(n, @@allowed_handle)
|
16
|
+
end
|
17
|
+
|
18
|
+
def _gen_secret(n, chars=nil)
|
19
|
+
OpenID::CryptUtil.random_string(n, chars)
|
20
|
+
end
|
21
|
+
|
22
|
+
def _gen_assoc(issued, lifetime=600)
|
23
|
+
secret = _gen_secret(20)
|
24
|
+
handle = _gen_handle(128)
|
25
|
+
OpenID::Association.new(handle, secret, Time.now + issued, lifetime,
|
26
|
+
'HMAC-SHA1')
|
27
|
+
end
|
28
|
+
|
29
|
+
def _check_retrieve(url, handle=nil, expected=nil)
|
30
|
+
ret_assoc = @store.get_association(url, handle)
|
31
|
+
|
32
|
+
if expected.nil?
|
33
|
+
assert_nil(ret_assoc)
|
34
|
+
else
|
35
|
+
assert_equal(expected, ret_assoc)
|
36
|
+
assert_equal(expected.handle, ret_assoc.handle)
|
37
|
+
assert_equal(expected.secret, ret_assoc.secret)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def _check_remove(url, handle, expected)
|
42
|
+
present = @store.remove_association(url, handle)
|
43
|
+
assert_equal(expected, present)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_store
|
47
|
+
server_url = "http://www.myopenid.com/openid"
|
48
|
+
assoc = _gen_assoc(issued=0)
|
49
|
+
|
50
|
+
# Make sure that a missing association returns no result
|
51
|
+
_check_retrieve(server_url)
|
52
|
+
|
53
|
+
# Check that after storage, getting returns the same result
|
54
|
+
@store.store_association(server_url, assoc)
|
55
|
+
_check_retrieve(server_url, nil, assoc)
|
56
|
+
|
57
|
+
# more than once
|
58
|
+
_check_retrieve(server_url, nil, assoc)
|
59
|
+
|
60
|
+
# Storing more than once has no ill effect
|
61
|
+
@store.store_association(server_url, assoc)
|
62
|
+
_check_retrieve(server_url, nil, assoc)
|
63
|
+
|
64
|
+
# Removing an association that does not exist returns not present
|
65
|
+
_check_remove(server_url, assoc.handle + 'x', false)
|
66
|
+
|
67
|
+
# Removing an association that does not exist returns not present
|
68
|
+
_check_remove(server_url + 'x', assoc.handle, false)
|
69
|
+
|
70
|
+
# Removing an association that is present returns present
|
71
|
+
_check_remove(server_url, assoc.handle, true)
|
72
|
+
|
73
|
+
# but not present on subsequent calls
|
74
|
+
_check_remove(server_url, assoc.handle, false)
|
75
|
+
|
76
|
+
# Put assoc back in the store
|
77
|
+
@store.store_association(server_url, assoc)
|
78
|
+
|
79
|
+
# More recent and expires after assoc
|
80
|
+
assoc2 = _gen_assoc(issued=1)
|
81
|
+
@store.store_association(server_url, assoc2)
|
82
|
+
|
83
|
+
# After storing an association with a different handle, but the
|
84
|
+
# same server_url, the handle with the later expiration is returned.
|
85
|
+
_check_retrieve(server_url, nil, assoc2)
|
86
|
+
|
87
|
+
# We can still retrieve the older association
|
88
|
+
_check_retrieve(server_url, assoc.handle, assoc)
|
89
|
+
|
90
|
+
# Plus we can retrieve the association with the later expiration
|
91
|
+
# explicitly
|
92
|
+
_check_retrieve(server_url, assoc2.handle, assoc2)
|
93
|
+
|
94
|
+
# More recent, and expires earlier than assoc2 or assoc. Make sure
|
95
|
+
# that we're picking the one with the latest issued date and not
|
96
|
+
# taking into account the expiration.
|
97
|
+
assoc3 = _gen_assoc(issued=2, lifetime=100)
|
98
|
+
@store.store_association(server_url, assoc3)
|
99
|
+
|
100
|
+
_check_retrieve(server_url, nil, assoc3)
|
101
|
+
_check_retrieve(server_url, assoc.handle, assoc)
|
102
|
+
_check_retrieve(server_url, assoc2.handle, assoc2)
|
103
|
+
_check_retrieve(server_url, assoc3.handle, assoc3)
|
104
|
+
|
105
|
+
_check_remove(server_url, assoc2.handle, true)
|
106
|
+
|
107
|
+
_check_retrieve(server_url, nil, assoc3)
|
108
|
+
_check_retrieve(server_url, assoc.handle, assoc)
|
109
|
+
_check_retrieve(server_url, assoc2.handle, nil)
|
110
|
+
_check_retrieve(server_url, assoc3.handle, assoc3)
|
111
|
+
|
112
|
+
_check_remove(server_url, assoc2.handle, false)
|
113
|
+
_check_remove(server_url, assoc3.handle, true)
|
114
|
+
|
115
|
+
_check_retrieve(server_url, nil, assoc)
|
116
|
+
_check_retrieve(server_url, assoc.handle, assoc)
|
117
|
+
_check_retrieve(server_url, assoc2.handle, nil)
|
118
|
+
_check_retrieve(server_url, assoc3.handle, nil)
|
119
|
+
|
120
|
+
_check_remove(server_url, assoc2.handle, false)
|
121
|
+
_check_remove(server_url, assoc.handle, true)
|
122
|
+
_check_remove(server_url, assoc3.handle, false)
|
123
|
+
|
124
|
+
_check_retrieve(server_url, nil, nil)
|
125
|
+
_check_retrieve(server_url, assoc.handle, nil)
|
126
|
+
_check_retrieve(server_url, assoc2.handle, nil)
|
127
|
+
_check_retrieve(server_url, assoc3.handle, nil)
|
128
|
+
|
129
|
+
_check_remove(server_url, assoc2.handle, false)
|
130
|
+
_check_remove(server_url, assoc.handle, false)
|
131
|
+
_check_remove(server_url, assoc3.handle, false)
|
132
|
+
|
133
|
+
assocValid1 = _gen_assoc(-3600, 7200)
|
134
|
+
assocValid2 = _gen_assoc(-5)
|
135
|
+
assocExpired1 = _gen_assoc(-7200, 3600)
|
136
|
+
assocExpired2 = _gen_assoc(-7200, 3600)
|
137
|
+
|
138
|
+
@store.cleanup_associations
|
139
|
+
@store.store_association(server_url + '1', assocValid1)
|
140
|
+
@store.store_association(server_url + '1', assocExpired1)
|
141
|
+
@store.store_association(server_url + '2', assocExpired2)
|
142
|
+
@store.store_association(server_url + '3', assocValid2)
|
143
|
+
|
144
|
+
cleaned = @store.cleanup_associations()
|
145
|
+
assert_equal(2, cleaned, "cleaned up associations")
|
146
|
+
end
|
147
|
+
|
148
|
+
def _check_use_nonce(nonce, expected, server_url, msg='')
|
149
|
+
stamp, salt = OpenID::Nonce::split_nonce(nonce)
|
150
|
+
actual = @store.use_nonce(server_url, stamp, salt)
|
151
|
+
assert_equal(expected, actual, msg)
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_nonce
|
155
|
+
server_url = "http://www.myopenid.com/openid"
|
156
|
+
[server_url, ''].each{|url|
|
157
|
+
nonce1 = OpenID::Nonce::mk_nonce
|
158
|
+
|
159
|
+
_check_use_nonce(nonce1, true, url, "#{url}: nonce allowed by default")
|
160
|
+
_check_use_nonce(nonce1, false, url, "#{url}: nonce not allowed twice")
|
161
|
+
_check_use_nonce(nonce1, false, url, "#{url}: nonce not allowed third time")
|
162
|
+
|
163
|
+
# old nonces shouldn't pass
|
164
|
+
old_nonce = OpenID::Nonce::mk_nonce(3600)
|
165
|
+
_check_use_nonce(old_nonce, false, url, "Old nonce #{old_nonce.inspect} passed")
|
166
|
+
|
167
|
+
}
|
168
|
+
|
169
|
+
now = Time.now.to_i
|
170
|
+
old_nonce1 = OpenID::Nonce::mk_nonce(now - 20000)
|
171
|
+
old_nonce2 = OpenID::Nonce::mk_nonce(now - 10000)
|
172
|
+
recent_nonce = OpenID::Nonce::mk_nonce(now - 600)
|
173
|
+
|
174
|
+
orig_skew = OpenID::Nonce.skew
|
175
|
+
OpenID::Nonce.skew = 0
|
176
|
+
count = @store.cleanup_nonces
|
177
|
+
OpenID::Nonce.skew = 1000000
|
178
|
+
ts, salt = OpenID::Nonce::split_nonce(old_nonce1)
|
179
|
+
assert(@store.use_nonce(server_url, ts, salt), "oldnonce1")
|
180
|
+
ts, salt = OpenID::Nonce::split_nonce(old_nonce2)
|
181
|
+
assert(@store.use_nonce(server_url, ts, salt), "oldnonce2")
|
182
|
+
ts, salt = OpenID::Nonce::split_nonce(recent_nonce)
|
183
|
+
assert(@store.use_nonce(server_url, ts, salt), "recent_nonce")
|
184
|
+
|
185
|
+
|
186
|
+
OpenID::Nonce.skew = 1000
|
187
|
+
cleaned = @store.cleanup_nonces
|
188
|
+
assert_equal(2, cleaned, "Cleaned #{cleaned} nonces")
|
189
|
+
|
190
|
+
OpenID::Nonce.skew = 100000
|
191
|
+
ts, salt = OpenID::Nonce::split_nonce(old_nonce1)
|
192
|
+
assert(@store.use_nonce(server_url, ts, salt), "oldnonce1 after cleanup")
|
193
|
+
ts, salt = OpenID::Nonce::split_nonce(old_nonce2)
|
194
|
+
assert(@store.use_nonce(server_url, ts, salt), "oldnonce2 after cleanup")
|
195
|
+
ts, salt = OpenID::Nonce::split_nonce(recent_nonce)
|
196
|
+
assert(!@store.use_nonce(server_url, ts, salt), "recent_nonce after cleanup")
|
197
|
+
|
198
|
+
OpenID::Nonce.skew = orig_skew
|
199
|
+
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
class TestARStore < Test::Unit::TestCase
|
205
|
+
include StoreTestCase
|
206
|
+
|
207
|
+
def setup
|
208
|
+
@store = ActiveRecordStore.new
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
|
data/todos.txt
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
- make sure the store can be easily used outside of rails (e.g. try it out with sinatra)
|
2
|
+
- do some rake tasks to create the database tables and stuff when using active record outside of rails (e.g. with sinatra)
|
3
|
+
- make sure that requiring the active_record_openid_store outside or rails works properly
|
4
|
+
- add some specs
|
5
|
+
- fix up some of the code (after specs have been added)
|
metadata
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active_record_openid_store
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alan Skorkin
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-07-20 00:00:00 +10:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: ruby-openid
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 2.1.0
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: "0"
|
36
|
+
type: :development
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: rspec
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 2.5.0
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: json
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ~>
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: 1.4.3
|
58
|
+
type: :development
|
59
|
+
version_requirements: *id004
|
60
|
+
description: A store is required by an OpenID server and optionally by the consumer to store associations, nonces, and auth key information across requests and processes. If rails is distributed across several machines, they must must all have access to the same OpenID store data, so the FilesystemStore won't do. The code here is copied from the openid-ruby library examples. All I did was move some things around, add a namespace and package it all up as a rails engine/plugin, with some conveniences, for use with Rails 3.
|
61
|
+
email:
|
62
|
+
- alan@skorks.com
|
63
|
+
executables: []
|
64
|
+
|
65
|
+
extensions: []
|
66
|
+
|
67
|
+
extra_rdoc_files: []
|
68
|
+
|
69
|
+
files:
|
70
|
+
- .gitignore
|
71
|
+
- .rspec
|
72
|
+
- .rvmrc
|
73
|
+
- Gemfile
|
74
|
+
- README.rdoc
|
75
|
+
- Rakefile
|
76
|
+
- active_record_openid_store.gemspec
|
77
|
+
- app/models/active_record_openid_store/association.rb
|
78
|
+
- app/models/active_record_openid_store/nonce.rb
|
79
|
+
- lib/active_record_openid_store.rb
|
80
|
+
- lib/active_record_openid_store/active_record_store.rb
|
81
|
+
- lib/active_record_openid_store/engine.rb
|
82
|
+
- lib/active_record_openid_store/railties/tasks.rake
|
83
|
+
- lib/active_record_openid_store/version.rb
|
84
|
+
- lib/generators/active_record_openid_store/USAGE
|
85
|
+
- lib/generators/active_record_openid_store/active_record_openid_store_generator.rb
|
86
|
+
- lib/generators/active_record_openid_store/templates/migration.rb
|
87
|
+
- spec/spec_helper.rb
|
88
|
+
- test/store_test.rb
|
89
|
+
- todos.txt
|
90
|
+
has_rdoc: true
|
91
|
+
homepage: https://github.com/skorks/active_record_openid_store
|
92
|
+
licenses: []
|
93
|
+
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: "0"
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: "0"
|
111
|
+
requirements: []
|
112
|
+
|
113
|
+
rubyforge_project: active_record_openid_store
|
114
|
+
rubygems_version: 1.6.2
|
115
|
+
signing_key:
|
116
|
+
specification_version: 3
|
117
|
+
summary: An Active Record-based OpenID store
|
118
|
+
test_files:
|
119
|
+
- spec/spec_helper.rb
|
120
|
+
- test/store_test.rb
|