ruby-openid 1.1.4 → 2.0.1
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.
- data/INSTALL +0 -9
- data/README +21 -22
- data/UPGRADE +117 -0
- data/admin/runtests.rb +36 -0
- data/examples/README +13 -21
- data/examples/active_record_openid_store/README +8 -3
- data/examples/active_record_openid_store/XXX_add_open_id_store_to_db.rb +4 -8
- data/examples/active_record_openid_store/XXX_upgrade_open_id_store.rb +26 -0
- data/examples/active_record_openid_store/lib/association.rb +2 -0
- data/examples/active_record_openid_store/lib/openid_ar_store.rb +22 -47
- data/examples/active_record_openid_store/test/store_test.rb +78 -48
- data/examples/discover +46 -0
- data/examples/{rails_server → rails_openid}/README +0 -0
- data/examples/{rails_server → rails_openid}/Rakefile +0 -0
- data/examples/{rails_server → rails_openid}/app/controllers/application.rb +0 -0
- data/examples/rails_openid/app/controllers/consumer_controller.rb +115 -0
- data/examples/{rails_server → rails_openid}/app/controllers/login_controller.rb +10 -2
- data/examples/rails_openid/app/controllers/server_controller.rb +265 -0
- data/examples/{rails_server → rails_openid}/app/helpers/application_helper.rb +0 -0
- data/examples/{rails_server → rails_openid}/app/helpers/login_helper.rb +0 -0
- data/examples/{rails_server → rails_openid}/app/helpers/server_helper.rb +0 -0
- data/examples/rails_openid/app/views/consumer/index.rhtml +81 -0
- data/examples/rails_openid/app/views/consumer/start.rhtml +8 -0
- data/examples/{rails_server → rails_openid}/app/views/layouts/server.rhtml +0 -0
- data/examples/{rails_server → rails_openid}/app/views/login/index.rhtml +1 -1
- data/examples/rails_openid/app/views/server/decide.rhtml +26 -0
- data/examples/{rails_server → rails_openid}/config/boot.rb +0 -0
- data/examples/{rails_server → rails_openid}/config/database.yml +0 -0
- data/examples/{rails_server → rails_openid}/config/environment.rb +0 -0
- data/examples/{rails_server → rails_openid}/config/environments/development.rb +0 -0
- data/examples/{rails_server → rails_openid}/config/environments/production.rb +0 -0
- data/examples/{rails_server → rails_openid}/config/environments/test.rb +0 -0
- data/examples/{rails_server → rails_openid}/config/routes.rb +2 -1
- data/examples/{rails_server → rails_openid}/doc/README_FOR_APP +0 -0
- data/examples/{rails_server → rails_openid}/public/404.html +0 -0
- data/examples/{rails_server → rails_openid}/public/500.html +0 -0
- data/examples/{rails_server → rails_openid}/public/dispatch.cgi +0 -0
- data/examples/{rails_server → rails_openid}/public/dispatch.fcgi +0 -0
- data/examples/{rails_server → rails_openid}/public/dispatch.rb +0 -0
- data/examples/{rails_server → rails_openid}/public/favicon.ico +0 -0
- data/examples/rails_openid/public/images/openid_login_bg.gif +0 -0
- data/examples/{rails_server → rails_openid}/public/javascripts/controls.js +0 -0
- data/examples/{rails_server → rails_openid}/public/javascripts/dragdrop.js +0 -0
- data/examples/{rails_server → rails_openid}/public/javascripts/effects.js +0 -0
- data/examples/{rails_server → rails_openid}/public/javascripts/prototype.js +0 -0
- data/examples/{rails_server → rails_openid}/public/robots.txt +0 -0
- data/examples/{rails_server → rails_openid}/script/about +0 -0
- data/examples/{rails_server → rails_openid}/script/breakpointer +0 -0
- data/examples/{rails_server → rails_openid}/script/console +0 -0
- data/examples/{rails_server → rails_openid}/script/destroy +0 -0
- data/examples/{rails_server → rails_openid}/script/generate +0 -0
- data/examples/{rails_server → rails_openid}/script/performance/benchmarker +0 -0
- data/examples/{rails_server → rails_openid}/script/performance/profiler +0 -0
- data/examples/{rails_server → rails_openid}/script/plugin +0 -0
- data/examples/{rails_server → rails_openid}/script/process/reaper +0 -0
- data/examples/{rails_server → rails_openid}/script/process/spawner +0 -0
- data/examples/{rails_server → rails_openid}/script/process/spinner +0 -0
- data/examples/{rails_server → rails_openid}/script/runner +0 -0
- data/examples/{rails_server → rails_openid}/script/server +0 -0
- data/examples/{rails_server → rails_openid}/test/functional/login_controller_test.rb +0 -0
- data/examples/{rails_server → rails_openid}/test/functional/server_controller_test.rb +0 -0
- data/examples/{rails_server → rails_openid}/test/test_helper.rb +0 -0
- data/lib/{hmac.rb → hmac/hmac.rb} +0 -0
- data/lib/{hmac-sha1.rb → hmac/sha1.rb} +1 -1
- data/lib/{hmac-sha2.rb → hmac/sha2.rb} +1 -1
- data/lib/openid/association.rb +213 -73
- data/lib/openid/consumer/associationmanager.rb +338 -0
- data/lib/openid/consumer/checkid_request.rb +175 -0
- data/lib/openid/consumer/discovery.rb +480 -0
- data/lib/openid/consumer/discovery_manager.rb +123 -0
- data/lib/openid/consumer/html_parse.rb +136 -0
- data/lib/openid/consumer/idres.rb +525 -0
- data/lib/openid/consumer/responses.rb +133 -0
- data/lib/openid/consumer.rb +280 -807
- data/lib/openid/cryptutil.rb +85 -0
- data/lib/openid/dh.rb +60 -23
- data/lib/openid/extension.rb +31 -0
- data/lib/openid/extensions/ax.rb +506 -0
- data/lib/openid/extensions/pape.rb +182 -0
- data/lib/openid/extensions/sreg.rb +275 -0
- data/lib/openid/extras.rb +11 -0
- data/lib/openid/fetchers.rb +132 -93
- data/lib/openid/kvform.rb +133 -0
- data/lib/openid/kvpost.rb +56 -0
- data/lib/openid/message.rb +534 -0
- data/lib/openid/protocolerror.rb +6 -0
- data/lib/openid/server.rb +1215 -666
- data/lib/openid/store/filesystem.rb +271 -0
- data/lib/openid/store/interface.rb +75 -0
- data/lib/openid/store/memory.rb +84 -0
- data/lib/openid/store/nonce.rb +68 -0
- data/lib/openid/trustroot.rb +314 -87
- data/lib/openid/urinorm.rb +37 -34
- data/lib/openid/util.rb +42 -220
- data/lib/openid/yadis/accept.rb +148 -0
- data/lib/openid/yadis/constants.rb +21 -0
- data/lib/openid/yadis/discovery.rb +153 -0
- data/lib/openid/yadis/filters.rb +205 -0
- data/lib/openid/{htmltokenizer.rb → yadis/htmltokenizer.rb} +1 -54
- data/lib/openid/yadis/parsehtml.rb +36 -0
- data/lib/openid/yadis/services.rb +42 -0
- data/lib/openid/yadis/xrds.rb +171 -0
- data/lib/openid/yadis/xri.rb +90 -0
- data/lib/openid/yadis/xrires.rb +106 -0
- data/lib/openid.rb +1 -4
- data/test/data/accept.txt +124 -0
- data/test/data/dh.txt +29 -0
- data/test/data/example-xrds.xml +14 -0
- data/test/data/linkparse.txt +587 -0
- data/test/data/n2b64 +650 -0
- data/test/data/test1-discover.txt +137 -0
- data/test/data/test1-parsehtml.txt +128 -0
- data/test/data/test_discover/openid.html +11 -0
- data/test/data/test_discover/openid2.html +11 -0
- data/test/data/test_discover/openid2_xrds.xml +12 -0
- data/test/data/test_discover/openid2_xrds_no_local_id.xml +11 -0
- data/test/data/test_discover/openid_1_and_2.html +11 -0
- data/test/data/test_discover/openid_1_and_2_xrds.xml +16 -0
- data/test/data/test_discover/openid_1_and_2_xrds_bad_delegate.xml +17 -0
- data/test/data/test_discover/openid_and_yadis.html +12 -0
- data/test/data/test_discover/openid_no_delegate.html +10 -0
- data/test/data/test_discover/yadis_0entries.xml +12 -0
- data/test/data/test_discover/yadis_2_bad_local_id.xml +15 -0
- data/test/data/test_discover/yadis_2entries_delegate.xml +22 -0
- data/test/data/test_discover/yadis_2entries_idp.xml +21 -0
- data/test/data/test_discover/yadis_another_delegate.xml +14 -0
- data/test/data/test_discover/yadis_idp.xml +12 -0
- data/test/data/test_discover/yadis_idp_delegate.xml +13 -0
- data/test/data/test_discover/yadis_no_delegate.xml +11 -0
- data/test/data/test_xrds/=j3h.2007.11.14.xrds +25 -0
- data/test/data/test_xrds/README +12 -0
- data/test/data/test_xrds/delegated-20060809-r1.xrds +34 -0
- data/test/data/test_xrds/delegated-20060809-r2.xrds +34 -0
- data/test/data/test_xrds/delegated-20060809.xrds +34 -0
- data/test/data/test_xrds/no-xrd.xml +7 -0
- data/test/data/test_xrds/not-xrds.xml +2 -0
- data/test/data/test_xrds/prefixsometimes.xrds +34 -0
- data/test/data/test_xrds/ref.xrds +109 -0
- data/test/data/test_xrds/sometimesprefix.xrds +34 -0
- data/test/data/test_xrds/spoof1.xrds +25 -0
- data/test/data/test_xrds/spoof2.xrds +25 -0
- data/test/data/test_xrds/spoof3.xrds +37 -0
- data/test/data/test_xrds/status222.xrds +9 -0
- data/test/data/test_xrds/valid-populated-xrds.xml +39 -0
- data/test/data/trustroot.txt +147 -0
- data/test/discoverdata.rb +131 -0
- data/test/test_accept.rb +170 -0
- data/test/test_association.rb +266 -0
- data/test/test_associationmanager.rb +899 -0
- data/test/test_ax.rb +587 -0
- data/test/test_checkid_request.rb +297 -0
- data/test/test_consumer.rb +257 -0
- data/test/test_cryptutil.rb +117 -0
- data/test/test_dh.rb +86 -0
- data/test/test_discover.rb +772 -0
- data/test/test_discovery_manager.rb +262 -0
- data/test/test_extras.rb +35 -0
- data/test/test_fetchers.rb +472 -0
- data/test/test_filters.rb +270 -0
- data/test/test_idres.rb +816 -0
- data/test/test_kvform.rb +165 -0
- data/test/test_kvpost.rb +65 -0
- data/test/test_linkparse.rb +101 -0
- data/test/test_message.rb +1058 -0
- data/test/test_nonce.rb +89 -0
- data/test/test_openid_yadis.rb +178 -0
- data/test/test_pape.rb +233 -0
- data/test/test_parsehtml.rb +80 -0
- data/test/test_responses.rb +63 -0
- data/test/test_server.rb +2270 -0
- data/test/test_sreg.rb +479 -0
- data/test/test_stores.rb +269 -0
- data/test/test_trustroot.rb +112 -0
- data/test/{urinorm.rb → test_urinorm.rb} +6 -3
- data/test/test_util.rb +144 -0
- data/test/test_xrds.rb +160 -0
- data/test/test_xri.rb +48 -0
- data/test/test_xrires.rb +63 -0
- data/test/test_yadis_discovery.rb +207 -0
- data/test/testutil.rb +116 -0
- data/test/util.rb +47 -50
- metadata +233 -143
- data/examples/consumer.rb +0 -290
- data/examples/rails_openid_login_generator/openid_login_generator-0.1.gem +0 -0
- data/examples/rails_server/app/controllers/server_controller.rb +0 -190
- data/examples/rails_server/app/views/server/decide.rhtml +0 -11
- data/examples/rails_server/public/images/rails.png +0 -0
- data/lib/hmac-md5.rb +0 -11
- data/lib/hmac-rmd160.rb +0 -11
- data/lib/openid/discovery.rb +0 -122
- data/lib/openid/filestore.rb +0 -315
- data/lib/openid/parse.rb +0 -23
- data/lib/openid/service.rb +0 -147
- data/lib/openid/stores.rb +0 -178
- data/test/assoc.rb +0 -38
- data/test/consumer.rb +0 -376
- data/test/data/brian.xrds +0 -16
- data/test/data/brianellin.mylid.xrds +0 -42
- data/test/dh.rb +0 -20
- data/test/extensions.rb +0 -30
- data/test/linkparse.rb +0 -305
- data/test/runtests.rb +0 -22
- data/test/server2.rb +0 -1053
- data/test/service.rb +0 -47
- data/test/storetestcase.rb +0 -172
- data/test/teststore.rb +0 -47
- data/test/trustroot.rb +0 -117
|
@@ -4,46 +4,43 @@ RAILS_ENV = "test"
|
|
|
4
4
|
require File.expand_path(File.join(File.dirname(__FILE__), '../../../../config/environment.rb'))
|
|
5
5
|
|
|
6
6
|
module StoreTestCase
|
|
7
|
-
|
|
8
7
|
@@allowed_handle = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
|
|
9
8
|
@@allowed_nonce = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
10
|
-
|
|
9
|
+
|
|
11
10
|
def _gen_nonce
|
|
12
|
-
OpenID::
|
|
11
|
+
OpenID::CryptUtil.random_string(8, @@allowed_nonce)
|
|
13
12
|
end
|
|
14
13
|
|
|
15
14
|
def _gen_handle(n)
|
|
16
|
-
OpenID::
|
|
15
|
+
OpenID::CryptUtil.random_string(n, @@allowed_handle)
|
|
17
16
|
end
|
|
18
17
|
|
|
19
18
|
def _gen_secret(n, chars=nil)
|
|
20
|
-
OpenID::
|
|
19
|
+
OpenID::CryptUtil.random_string(n, chars)
|
|
21
20
|
end
|
|
22
21
|
|
|
23
22
|
def _gen_assoc(issued, lifetime=600)
|
|
24
23
|
secret = _gen_secret(20)
|
|
25
24
|
handle = _gen_handle(128)
|
|
26
|
-
OpenID::Association.new(handle, secret, Time.now
|
|
25
|
+
OpenID::Association.new(handle, secret, Time.now + issued, lifetime,
|
|
27
26
|
'HMAC-SHA1')
|
|
28
27
|
end
|
|
29
|
-
|
|
28
|
+
|
|
30
29
|
def _check_retrieve(url, handle=nil, expected=nil)
|
|
31
30
|
ret_assoc = @store.get_association(url, handle)
|
|
32
31
|
|
|
33
|
-
if expected.nil?
|
|
32
|
+
if expected.nil?
|
|
34
33
|
assert_nil(ret_assoc)
|
|
35
34
|
else
|
|
36
|
-
assert_equal(
|
|
37
|
-
assert_equal(
|
|
38
|
-
assert_equal(
|
|
35
|
+
assert_equal(expected, ret_assoc)
|
|
36
|
+
assert_equal(expected.handle, ret_assoc.handle)
|
|
37
|
+
assert_equal(expected.secret, ret_assoc.secret)
|
|
39
38
|
end
|
|
40
39
|
end
|
|
41
40
|
|
|
42
41
|
def _check_remove(url, handle, expected)
|
|
43
42
|
present = @store.remove_association(url, handle)
|
|
44
|
-
|
|
45
|
-
assert ((not expected_present and not present) or \
|
|
46
|
-
(expected_present and present))
|
|
43
|
+
assert_equal(expected, present)
|
|
47
44
|
end
|
|
48
45
|
|
|
49
46
|
def test_store
|
|
@@ -132,50 +129,83 @@ module StoreTestCase
|
|
|
132
129
|
_check_remove(server_url, assoc2.handle, false)
|
|
133
130
|
_check_remove(server_url, assoc.handle, false)
|
|
134
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")
|
|
135
146
|
end
|
|
136
|
-
|
|
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
|
+
|
|
137
154
|
def test_nonce
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
+
|
|
166
185
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
+
|
|
170
200
|
end
|
|
171
|
-
|
|
172
201
|
end
|
|
173
202
|
|
|
203
|
+
|
|
174
204
|
class TestARStore < Test::Unit::TestCase
|
|
175
205
|
include StoreTestCase
|
|
176
206
|
|
|
177
207
|
def setup
|
|
178
|
-
@store =
|
|
208
|
+
@store = ActiveRecordStore.new
|
|
179
209
|
end
|
|
180
210
|
|
|
181
211
|
end
|
data/examples/discover
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require "openid/consumer/discovery"
|
|
3
|
+
|
|
4
|
+
$names = [[:server_url, "Server URL "],
|
|
5
|
+
[:local_id, "Local ID "],
|
|
6
|
+
[:canonical_id, "Canonical ID"],
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
def show_services(user_input, normalized, services)
|
|
10
|
+
puts " Claimed identifier: #{normalized}"
|
|
11
|
+
if services.empty?
|
|
12
|
+
puts " No OpenID services found"
|
|
13
|
+
puts
|
|
14
|
+
else
|
|
15
|
+
puts " Discovered services:"
|
|
16
|
+
n = 0
|
|
17
|
+
services.each do |service|
|
|
18
|
+
n += 1
|
|
19
|
+
puts " #{n}."
|
|
20
|
+
$names.each do |meth, name|
|
|
21
|
+
val = service.send(meth)
|
|
22
|
+
if val
|
|
23
|
+
printf(" %s: %s\n", name, val)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
puts " Type URIs:"
|
|
27
|
+
for type_uri in service.type_uris
|
|
28
|
+
puts " * #{type_uri}"
|
|
29
|
+
end
|
|
30
|
+
puts
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
ARGV.each do |openid_identifier|
|
|
36
|
+
puts "=" * 50
|
|
37
|
+
puts "Running discovery on #{openid_identifier}"
|
|
38
|
+
begin
|
|
39
|
+
normalized_identifier, services = OpenID.discover(openid_identifier)
|
|
40
|
+
rescue OpenID::Yadis::DiscoveryFailure => why
|
|
41
|
+
puts "Discovery failed: #{why.message}"
|
|
42
|
+
puts
|
|
43
|
+
else
|
|
44
|
+
show_services(openid_identifier, normalized_identifier, services)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
|
|
3
|
+
require "openid"
|
|
4
|
+
require 'openid/extensions/sreg'
|
|
5
|
+
require 'openid/extensions/pape'
|
|
6
|
+
require 'openid/store/filesystem'
|
|
7
|
+
|
|
8
|
+
class ConsumerController < ApplicationController
|
|
9
|
+
layout nil
|
|
10
|
+
|
|
11
|
+
def index
|
|
12
|
+
# render an openid form
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def start
|
|
16
|
+
begin
|
|
17
|
+
oidreq = consumer.begin(params[:openid_identifier])
|
|
18
|
+
rescue OpenID::OpenIDError => e
|
|
19
|
+
flash[:error] = "Discovery failed for #{params[:openid_identifier]}: #{e}"
|
|
20
|
+
redirect_to :action => 'index'
|
|
21
|
+
return
|
|
22
|
+
end
|
|
23
|
+
if params[:use_sreg]
|
|
24
|
+
sregreq = OpenID::SReg::Request.new
|
|
25
|
+
# required fields
|
|
26
|
+
sregreq.request_fields(['email','nickname'], true)
|
|
27
|
+
# optional fields
|
|
28
|
+
sregreq.request_fields(['dob', 'fullname'], false)
|
|
29
|
+
oidreq.add_extension(sregreq)
|
|
30
|
+
oidreq.return_to_args['did_sreg'] = 'y'
|
|
31
|
+
end
|
|
32
|
+
if params[:use_pape]
|
|
33
|
+
papereq = OpenID::PAPE::Request.new
|
|
34
|
+
papereq.add_policy_uri(OpenID::PAPE::AUTH_PHISHING_RESISTANT)
|
|
35
|
+
papereq.max_auth_age = 2*60*60
|
|
36
|
+
oidreq.add_extension(papereq)
|
|
37
|
+
oidreq.return_to_args['did_pape'] = 'y'
|
|
38
|
+
end
|
|
39
|
+
if params[:force_post]
|
|
40
|
+
oidreq.return_to_args['force_post']='x'*2048
|
|
41
|
+
end
|
|
42
|
+
return_to = url_for :action => 'complete', :only_path => false
|
|
43
|
+
realm = url_for :action => 'index', :only_path => false
|
|
44
|
+
|
|
45
|
+
if oidreq.send_redirect?(realm, return_to, params[:immediate])
|
|
46
|
+
redirect_to oidreq.redirect_url(realm, return_to, params[:immediate])
|
|
47
|
+
else
|
|
48
|
+
@form_text = oidreq.form_markup(realm, return_to, params[:immediate], {'id' => 'openid_form'})
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def complete
|
|
53
|
+
return_to = url_for(:action => 'complete', :only_path => false)
|
|
54
|
+
parameters = params.reject{|k,v|request.path_parameters[k]}
|
|
55
|
+
oidresp = consumer.complete(parameters, return_to)
|
|
56
|
+
case oidresp.status
|
|
57
|
+
when OpenID::Consumer::FAILURE
|
|
58
|
+
if oidresp.display_identifier
|
|
59
|
+
flash[:error] = ("Verification of #{oidresp.display_identifier}"\
|
|
60
|
+
" failed: #{oidresp.message}")
|
|
61
|
+
else
|
|
62
|
+
flash[:error] = "Verification failed: #{oidresp.message}"
|
|
63
|
+
end
|
|
64
|
+
when OpenID::Consumer::SUCCESS
|
|
65
|
+
flash[:success] = ("Verification of #{oidresp.display_identifier}"\
|
|
66
|
+
" succeeded.")
|
|
67
|
+
if params[:did_sreg]
|
|
68
|
+
sreg_resp = OpenID::SReg::Response.from_success_response(oidresp)
|
|
69
|
+
sreg_message = "Simple Registration data was requested"
|
|
70
|
+
if sreg_resp.empty?
|
|
71
|
+
sreg_message << ", but none was returned."
|
|
72
|
+
else
|
|
73
|
+
sreg_message << ". The following data were sent:"
|
|
74
|
+
sreg_resp.data.each {|k,v|
|
|
75
|
+
sreg_message << "<br/><b>#{k}</b>: #{v}"
|
|
76
|
+
}
|
|
77
|
+
end
|
|
78
|
+
flash[:sreg_results] = sreg_message
|
|
79
|
+
end
|
|
80
|
+
if params[:did_pape]
|
|
81
|
+
pape_resp = OpenID::PAPE::Response.from_success_response(oidresp)
|
|
82
|
+
pape_message = "A phishing resistant authentication method was requested"
|
|
83
|
+
if pape_resp.auth_policies.member? OpenID::PAPE::AUTH_PHISHING_RESISTANT
|
|
84
|
+
pape_message << ", and the server reported one."
|
|
85
|
+
else
|
|
86
|
+
pape_message << ", but the server did not report one."
|
|
87
|
+
end
|
|
88
|
+
if pape_resp.auth_age
|
|
89
|
+
pape_message << "<br><b>Authentication age:</b> #{pape_resp.auth_age} seconds"
|
|
90
|
+
end
|
|
91
|
+
if pape_resp.nist_auth_level
|
|
92
|
+
pape_message << "<br><b>NIST Auth Level:</b> #{pape_resp.nist_auth_level}"
|
|
93
|
+
end
|
|
94
|
+
flash[:pape_results] = pape_message
|
|
95
|
+
end
|
|
96
|
+
when OpenID::Consumer::SETUP_NEEDED
|
|
97
|
+
flash[:alert] = "Immediate request failed - Setup Needed"
|
|
98
|
+
when OpenID::Consumer::CANCEL
|
|
99
|
+
flash[:alert] = "OpenID transaction cancelled."
|
|
100
|
+
else
|
|
101
|
+
end
|
|
102
|
+
redirect_to :action => 'index'
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
private
|
|
106
|
+
|
|
107
|
+
def consumer
|
|
108
|
+
if @consumer.nil?
|
|
109
|
+
dir = Pathname.new(RAILS_ROOT).join('db').join('cstore')
|
|
110
|
+
store = OpenID::Store::Filesystem.new(dir)
|
|
111
|
+
@consumer = OpenID::Consumer.new(session, store)
|
|
112
|
+
end
|
|
113
|
+
return @consumer
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -5,19 +5,27 @@ class LoginController < ApplicationController
|
|
|
5
5
|
|
|
6
6
|
layout 'server'
|
|
7
7
|
|
|
8
|
+
def base_url
|
|
9
|
+
url_for(:controller => 'login', :action => nil, :only_path => false)
|
|
10
|
+
end
|
|
11
|
+
|
|
8
12
|
def index
|
|
13
|
+
response.headers['X-XRDS-Location'] = url_for(:controller => "server",
|
|
14
|
+
:action => "idp_xrds",
|
|
15
|
+
:only_path => false)
|
|
16
|
+
@base_url = base_url
|
|
9
17
|
# just show the login page
|
|
10
18
|
end
|
|
11
19
|
|
|
12
20
|
def submit
|
|
13
|
-
user =
|
|
21
|
+
user = params[:username]
|
|
14
22
|
|
|
15
23
|
# if we get a user, log them in by putting their username in
|
|
16
24
|
# the session hash.
|
|
17
25
|
unless user.nil?
|
|
18
26
|
session[:username] = user unless user.nil?
|
|
19
27
|
session[:approvals] = []
|
|
20
|
-
flash[:notice] = "Your OpenID URL is <b
|
|
28
|
+
flash[:notice] = "Your OpenID URL is <b>#{base_url}user/#{user}</b><br/><br/>Proceed to step 2 below."
|
|
21
29
|
else
|
|
22
30
|
flash[:error] = "Sorry, couldn't log you in. Try again."
|
|
23
31
|
end
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
|
|
3
|
+
# load the openid library, first trying rubygems
|
|
4
|
+
#begin
|
|
5
|
+
# require "rubygems"
|
|
6
|
+
# require_gem "ruby-openid", ">= 1.0"
|
|
7
|
+
#rescue LoadError
|
|
8
|
+
require "openid"
|
|
9
|
+
require "openid/consumer/discovery"
|
|
10
|
+
require 'openid/extensions/sreg'
|
|
11
|
+
require 'openid/extensions/pape'
|
|
12
|
+
require 'openid/store/filesystem'
|
|
13
|
+
#end
|
|
14
|
+
|
|
15
|
+
class ServerController < ApplicationController
|
|
16
|
+
|
|
17
|
+
include ServerHelper
|
|
18
|
+
include OpenID::Server
|
|
19
|
+
layout nil
|
|
20
|
+
|
|
21
|
+
def index
|
|
22
|
+
begin
|
|
23
|
+
oidreq = server.decode_request(params)
|
|
24
|
+
rescue ProtocolError => e
|
|
25
|
+
# invalid openid request, so just display a page with an error message
|
|
26
|
+
render_text e.to_s
|
|
27
|
+
return
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# no openid.mode was given
|
|
31
|
+
unless oidreq
|
|
32
|
+
render_text "This is an OpenID server endpoint."
|
|
33
|
+
return
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
oidresp = nil
|
|
37
|
+
|
|
38
|
+
if oidreq.kind_of?(CheckIDRequest)
|
|
39
|
+
|
|
40
|
+
identity = oidreq.identity
|
|
41
|
+
|
|
42
|
+
if oidreq.id_select
|
|
43
|
+
if oidreq.immediate
|
|
44
|
+
oidresp = oidreq.answer(false)
|
|
45
|
+
elsif session[:username].nil?
|
|
46
|
+
# The user hasn't logged in.
|
|
47
|
+
show_decision_page(oidreq)
|
|
48
|
+
return
|
|
49
|
+
else
|
|
50
|
+
# Else, set the identity to the one the user is using.
|
|
51
|
+
identity = url_for_user
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
if oidresp
|
|
56
|
+
nil
|
|
57
|
+
elsif self.is_authorized(identity, oidreq.trust_root)
|
|
58
|
+
oidresp = oidreq.answer(true, nil, identity)
|
|
59
|
+
|
|
60
|
+
# add the sreg response if requested
|
|
61
|
+
add_sreg(oidreq, oidresp)
|
|
62
|
+
# ditto pape
|
|
63
|
+
add_pape(oidreq, oidresp)
|
|
64
|
+
|
|
65
|
+
elsif oidreq.immediate
|
|
66
|
+
server_url = url_for :action => 'index'
|
|
67
|
+
oidresp = oidreq.answer(false, server_url)
|
|
68
|
+
|
|
69
|
+
else
|
|
70
|
+
show_decision_page(oidreq)
|
|
71
|
+
return
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
else
|
|
75
|
+
oidresp = server.handle_request(oidreq)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
self.render_response(oidresp)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def show_decision_page(oidreq, message="Do you trust this site with your identity?")
|
|
82
|
+
session[:last_oidreq] = oidreq
|
|
83
|
+
@oidreq = oidreq
|
|
84
|
+
|
|
85
|
+
if message
|
|
86
|
+
flash[:notice] = message
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
render :template => 'server/decide', :layout => 'server'
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def user_page
|
|
93
|
+
# Yadis content-negotiation: we want to return the xrds if asked for.
|
|
94
|
+
accept = request.env['HTTP_ACCEPT']
|
|
95
|
+
|
|
96
|
+
# This is not technically correct, and should eventually be updated
|
|
97
|
+
# to do real Accept header parsing and logic. Though I expect it will work
|
|
98
|
+
# 99% of the time.
|
|
99
|
+
if accept and accept.include?('application/xrds+xml')
|
|
100
|
+
user_xrds
|
|
101
|
+
return
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# content negotiation failed, so just render the user page
|
|
105
|
+
xrds_url = url_for(:controller=>'user',:action=>params[:username])+'/xrds'
|
|
106
|
+
identity_page = <<EOS
|
|
107
|
+
<html><head>
|
|
108
|
+
<meta http-equiv="X-XRDS-Location" content="#{xrds_url}" />
|
|
109
|
+
<link rel="openid.server" href="#{url_for :action => 'index'}" />
|
|
110
|
+
</head><body><p>OpenID identity page for #{params[:username]}</p>
|
|
111
|
+
</body></html>
|
|
112
|
+
EOS
|
|
113
|
+
|
|
114
|
+
# Also add the Yadis location header, so that they don't have
|
|
115
|
+
# to parse the html unless absolutely necessary.
|
|
116
|
+
response.headers['X-XRDS-Location'] = xrds_url
|
|
117
|
+
render_text identity_page
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def user_xrds
|
|
121
|
+
types = [
|
|
122
|
+
OpenID::OPENID_2_0_TYPE,
|
|
123
|
+
OpenID::OPENID_1_0_TYPE,
|
|
124
|
+
OpenID::SREG_URI,
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
render_xrds(types)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def idp_xrds
|
|
131
|
+
types = [
|
|
132
|
+
OpenID::OPENID_IDP_2_0_TYPE,
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
render_xrds(types)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def decision
|
|
139
|
+
oidreq = session[:last_oidreq]
|
|
140
|
+
session[:last_oidreq] = nil
|
|
141
|
+
|
|
142
|
+
if params[:yes].nil?
|
|
143
|
+
redirect_to oidreq.cancel_url
|
|
144
|
+
return
|
|
145
|
+
else
|
|
146
|
+
id_to_send = params[:id_to_send]
|
|
147
|
+
|
|
148
|
+
identity = oidreq.identity
|
|
149
|
+
if oidreq.id_select
|
|
150
|
+
if id_to_send and id_to_send != ""
|
|
151
|
+
session[:username] = id_to_send
|
|
152
|
+
session[:approvals] = []
|
|
153
|
+
identity = url_for_user
|
|
154
|
+
else
|
|
155
|
+
msg = "You must enter a username to in order to send " +
|
|
156
|
+
"an identifier to the Relying Party."
|
|
157
|
+
show_decision_page(oidreq, msg)
|
|
158
|
+
return
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
if session[:approvals]
|
|
163
|
+
session[:approvals] << oidreq.trust_root
|
|
164
|
+
else
|
|
165
|
+
session[:approvals] = [oidreq.trust_root]
|
|
166
|
+
end
|
|
167
|
+
oidresp = oidreq.answer(true, nil, identity)
|
|
168
|
+
add_sreg(oidreq, oidresp)
|
|
169
|
+
add_pape(oidreq, oidresp)
|
|
170
|
+
return self.render_response(oidresp)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
protected
|
|
175
|
+
|
|
176
|
+
def server
|
|
177
|
+
if @server.nil?
|
|
178
|
+
server_url = url_for :action => 'index', :only_path => false
|
|
179
|
+
dir = Pathname.new(RAILS_ROOT).join('db').join('openid-store')
|
|
180
|
+
store = OpenID::Store::Filesystem.new(dir)
|
|
181
|
+
@server = Server.new(store, server_url)
|
|
182
|
+
end
|
|
183
|
+
return @server
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def approved(trust_root)
|
|
187
|
+
return false if session[:approvals].nil?
|
|
188
|
+
return session[:approvals].member?(trust_root)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def is_authorized(identity_url, trust_root)
|
|
192
|
+
return (session[:username] and (identity_url == url_for_user) and self.approved(trust_root))
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def render_xrds(types)
|
|
196
|
+
type_str = ""
|
|
197
|
+
|
|
198
|
+
types.each { |uri|
|
|
199
|
+
type_str += "<Type>#{uri}</Type>\n "
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
yadis = <<EOS
|
|
203
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
204
|
+
<xrds:XRDS
|
|
205
|
+
xmlns:xrds="xri://$xrds"
|
|
206
|
+
xmlns="xri://$xrd*($v*2.0)">
|
|
207
|
+
<XRD>
|
|
208
|
+
<Service priority="0">
|
|
209
|
+
#{type_str}
|
|
210
|
+
<URI>#{url_for(:controller => 'server', :only_path => false)}</URI>
|
|
211
|
+
</Service>
|
|
212
|
+
</XRD>
|
|
213
|
+
</xrds:XRDS>
|
|
214
|
+
EOS
|
|
215
|
+
|
|
216
|
+
response.headers['content-type'] = 'application/xrds+xml'
|
|
217
|
+
render_text yadis
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def add_sreg(oidreq, oidresp)
|
|
221
|
+
# check for Simple Registration arguments and respond
|
|
222
|
+
sregreq = OpenID::SReg::Request.from_openid_request(oidreq)
|
|
223
|
+
|
|
224
|
+
return if sregreq.nil?
|
|
225
|
+
# In a real application, this data would be user-specific,
|
|
226
|
+
# and the user should be asked for permission to release
|
|
227
|
+
# it.
|
|
228
|
+
sreg_data = {
|
|
229
|
+
'nickname' => session[:username],
|
|
230
|
+
'fullname' => 'Mayor McCheese',
|
|
231
|
+
'email' => 'mayor@example.com'
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
sregresp = OpenID::SReg::Response.extract_response(sregreq, sreg_data)
|
|
235
|
+
oidresp.add_extension(sregresp)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def add_pape(oidreq, oidresp)
|
|
239
|
+
papereq = OpenID::PAPE::Request.from_openid_request(oidreq)
|
|
240
|
+
return if papereq.nil?
|
|
241
|
+
paperesp = OpenID::PAPE::Response.new
|
|
242
|
+
paperesp.nist_auth_level = 0 # we don't even do auth at all!
|
|
243
|
+
oidresp.add_extension(paperesp)
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def render_response(oidresp)
|
|
247
|
+
if oidresp.needs_signing
|
|
248
|
+
signed_response = server.signatory.sign(oidresp)
|
|
249
|
+
end
|
|
250
|
+
web_response = server.encode_response(oidresp)
|
|
251
|
+
|
|
252
|
+
case web_response.code
|
|
253
|
+
when HTTP_OK
|
|
254
|
+
render :text => web_response.body, :status => 200
|
|
255
|
+
|
|
256
|
+
when HTTP_REDIRECT
|
|
257
|
+
redirect_to web_response.headers['location']
|
|
258
|
+
|
|
259
|
+
else
|
|
260
|
+
render :text => web_response.body, :status => 400
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|