pelle-ruby-openid 2.1.8
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/CHANGELOG +215 -0
- data/CHANGES-2.1.0 +36 -0
- data/INSTALL +47 -0
- data/LICENSE +210 -0
- data/NOTICE +2 -0
- data/README +82 -0
- data/UPGRADE +127 -0
- data/VERSION +1 -0
- data/examples/README +32 -0
- data/examples/active_record_openid_store/README +58 -0
- data/examples/active_record_openid_store/XXX_add_open_id_store_to_db.rb +24 -0
- data/examples/active_record_openid_store/XXX_upgrade_open_id_store.rb +26 -0
- data/examples/active_record_openid_store/init.rb +8 -0
- data/examples/active_record_openid_store/lib/association.rb +10 -0
- data/examples/active_record_openid_store/lib/nonce.rb +3 -0
- data/examples/active_record_openid_store/lib/open_id_setting.rb +4 -0
- data/examples/active_record_openid_store/lib/openid_ar_store.rb +57 -0
- data/examples/active_record_openid_store/test/store_test.rb +212 -0
- data/examples/discover +49 -0
- data/examples/rails_openid/README +153 -0
- data/examples/rails_openid/Rakefile +10 -0
- data/examples/rails_openid/app/controllers/application.rb +4 -0
- data/examples/rails_openid/app/controllers/consumer_controller.rb +122 -0
- data/examples/rails_openid/app/controllers/login_controller.rb +45 -0
- data/examples/rails_openid/app/controllers/server_controller.rb +265 -0
- data/examples/rails_openid/app/helpers/application_helper.rb +3 -0
- data/examples/rails_openid/app/helpers/login_helper.rb +2 -0
- data/examples/rails_openid/app/helpers/server_helper.rb +9 -0
- data/examples/rails_openid/app/views/consumer/index.rhtml +81 -0
- data/examples/rails_openid/app/views/layouts/server.rhtml +68 -0
- data/examples/rails_openid/app/views/login/index.rhtml +56 -0
- data/examples/rails_openid/app/views/server/decide.rhtml +26 -0
- data/examples/rails_openid/config/boot.rb +19 -0
- data/examples/rails_openid/config/database.yml +74 -0
- data/examples/rails_openid/config/environment.rb +54 -0
- data/examples/rails_openid/config/environments/development.rb +19 -0
- data/examples/rails_openid/config/environments/production.rb +19 -0
- data/examples/rails_openid/config/environments/test.rb +19 -0
- data/examples/rails_openid/config/routes.rb +24 -0
- data/examples/rails_openid/doc/README_FOR_APP +2 -0
- data/examples/rails_openid/public/.htaccess +40 -0
- data/examples/rails_openid/public/404.html +8 -0
- data/examples/rails_openid/public/500.html +8 -0
- data/examples/rails_openid/public/dispatch.cgi +12 -0
- data/examples/rails_openid/public/dispatch.fcgi +26 -0
- data/examples/rails_openid/public/dispatch.rb +12 -0
- data/examples/rails_openid/public/favicon.ico +0 -0
- data/examples/rails_openid/public/images/openid_login_bg.gif +0 -0
- data/examples/rails_openid/public/javascripts/controls.js +750 -0
- data/examples/rails_openid/public/javascripts/dragdrop.js +584 -0
- data/examples/rails_openid/public/javascripts/effects.js +854 -0
- data/examples/rails_openid/public/javascripts/prototype.js +1785 -0
- data/examples/rails_openid/public/robots.txt +1 -0
- data/examples/rails_openid/script/about +3 -0
- data/examples/rails_openid/script/breakpointer +3 -0
- data/examples/rails_openid/script/console +3 -0
- data/examples/rails_openid/script/destroy +3 -0
- data/examples/rails_openid/script/generate +3 -0
- data/examples/rails_openid/script/performance/benchmarker +3 -0
- data/examples/rails_openid/script/performance/profiler +3 -0
- data/examples/rails_openid/script/plugin +3 -0
- data/examples/rails_openid/script/process/reaper +3 -0
- data/examples/rails_openid/script/process/spawner +3 -0
- data/examples/rails_openid/script/process/spinner +3 -0
- data/examples/rails_openid/script/runner +3 -0
- data/examples/rails_openid/script/server +3 -0
- data/examples/rails_openid/test/functional/login_controller_test.rb +18 -0
- data/examples/rails_openid/test/functional/server_controller_test.rb +18 -0
- data/examples/rails_openid/test/test_helper.rb +28 -0
- data/lib/hmac/hmac.rb +112 -0
- data/lib/hmac/sha1.rb +11 -0
- data/lib/hmac/sha2.rb +25 -0
- data/lib/openid/association.rb +249 -0
- data/lib/openid/consumer/associationmanager.rb +344 -0
- data/lib/openid/consumer/checkid_request.rb +186 -0
- data/lib/openid/consumer/discovery.rb +498 -0
- data/lib/openid/consumer/discovery_manager.rb +123 -0
- data/lib/openid/consumer/html_parse.rb +134 -0
- data/lib/openid/consumer/idres.rb +523 -0
- data/lib/openid/consumer/responses.rb +148 -0
- data/lib/openid/consumer.rb +395 -0
- data/lib/openid/cryptutil.rb +97 -0
- data/lib/openid/dh.rb +89 -0
- data/lib/openid/extension.rb +39 -0
- data/lib/openid/extensions/ax.rb +516 -0
- data/lib/openid/extensions/oauth.rb +91 -0
- data/lib/openid/extensions/pape.rb +179 -0
- data/lib/openid/extensions/sreg.rb +277 -0
- data/lib/openid/extras.rb +11 -0
- data/lib/openid/fetchers.rb +238 -0
- data/lib/openid/kvform.rb +136 -0
- data/lib/openid/kvpost.rb +58 -0
- data/lib/openid/message.rb +553 -0
- data/lib/openid/protocolerror.rb +8 -0
- data/lib/openid/server.rb +1544 -0
- data/lib/openid/store/filesystem.rb +271 -0
- data/lib/openid/store/interface.rb +75 -0
- data/lib/openid/store/memcache.rb +107 -0
- data/lib/openid/store/memory.rb +84 -0
- data/lib/openid/store/nonce.rb +68 -0
- data/lib/openid/trustroot.rb +349 -0
- data/lib/openid/urinorm.rb +75 -0
- data/lib/openid/util.rb +110 -0
- 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/yadis/htmltokenizer.rb +305 -0
- data/lib/openid/yadis/parsehtml.rb +45 -0
- data/lib/openid/yadis/services.rb +42 -0
- data/lib/openid/yadis/xrds.rb +155 -0
- data/lib/openid/yadis/xri.rb +90 -0
- data/lib/openid/yadis/xrires.rb +106 -0
- data/lib/openid.rb +20 -0
- data/setup.rb +1551 -0
- 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 +152 -0
- data/test/data/test_discover/malformed_meta_tag.html +19 -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/subsegments.xrds +58 -0
- data/test/data/test_xrds/valid-populated-xrds.xml +39 -0
- data/test/data/trustroot.txt +153 -0
- data/test/data/urinorm.txt +79 -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 +917 -0
- data/test/test_ax.rb +648 -0
- data/test/test_checkid_request.rb +294 -0
- data/test/test_consumer.rb +257 -0
- data/test/test_cryptutil.rb +119 -0
- data/test/test_dh.rb +86 -0
- data/test/test_discover.rb +838 -0
- data/test/test_discovery_manager.rb +262 -0
- data/test/test_extension.rb +46 -0
- data/test/test_extras.rb +35 -0
- data/test/test_fetchers.rb +538 -0
- data/test/test_filters.rb +270 -0
- data/test/test_idres.rb +963 -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 +1116 -0
- data/test/test_nonce.rb +89 -0
- data/test/test_oauth.rb +175 -0
- data/test/test_openid_yadis.rb +178 -0
- data/test/test_pape.rb +247 -0
- data/test/test_parsehtml.rb +80 -0
- data/test/test_responses.rb +63 -0
- data/test/test_server.rb +2457 -0
- data/test/test_sreg.rb +479 -0
- data/test/test_stores.rb +298 -0
- data/test/test_trustroot.rb +113 -0
- data/test/test_urinorm.rb +35 -0
- data/test/test_util.rb +145 -0
- data/test/test_xrds.rb +169 -0
- data/test/test_xri.rb +48 -0
- data/test/test_xrires.rb +63 -0
- data/test/test_yadis_discovery.rb +220 -0
- data/test/testutil.rb +127 -0
- data/test/util.rb +53 -0
- metadata +316 -0
data/UPGRADE
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
= Upgrading from the OpenID 1.x series library
|
|
2
|
+
|
|
3
|
+
== Consumer Upgrade
|
|
4
|
+
|
|
5
|
+
The flow is largely the same, however there are a number of significant
|
|
6
|
+
changes. The consumer example is helpful to look at:
|
|
7
|
+
examples/rails_openid/app/controllers/consumer_controller.rb
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
=== Stores
|
|
11
|
+
|
|
12
|
+
You will need to require the file for the store that you are using.
|
|
13
|
+
For the filesystem store, this is 'openid/stores/filesystem'
|
|
14
|
+
They are also now in modules. The filesystem store is
|
|
15
|
+
OpenID::Store::Filesystem
|
|
16
|
+
The format has changed, and you should remove your old store directory.
|
|
17
|
+
|
|
18
|
+
The ActiveRecord store ( examples/active_record_openid_store ) still needs
|
|
19
|
+
to be put in a plugin directory for your rails app. There's a migration
|
|
20
|
+
that needs to be run; examine the README in that directory.
|
|
21
|
+
|
|
22
|
+
Also, note that the stores now can be garbage collected with the method
|
|
23
|
+
store.cleanup
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
=== Starting the OpenID transaction
|
|
27
|
+
|
|
28
|
+
The OpenIDRequest object no longer has status codes. Instead,
|
|
29
|
+
consumer.begin raises an OpenID::OpenIDError if there is a problem
|
|
30
|
+
initiating the transaction, so you'll want something along the lines of:
|
|
31
|
+
|
|
32
|
+
begin
|
|
33
|
+
openid_request = consumer.begin(params[:openid_identifier])
|
|
34
|
+
rescue OpenID::OpenIDError => e
|
|
35
|
+
# display error e
|
|
36
|
+
return
|
|
37
|
+
end
|
|
38
|
+
#success case
|
|
39
|
+
|
|
40
|
+
Data regarding the OpenID server once lived in
|
|
41
|
+
openid_request.service
|
|
42
|
+
|
|
43
|
+
The corresponding object in the 2.0 lib can be retrieved with
|
|
44
|
+
openid_request.endpoint
|
|
45
|
+
|
|
46
|
+
Getting the unverified identifier: Where you once had
|
|
47
|
+
openid_request.identity_url
|
|
48
|
+
you will now want
|
|
49
|
+
openid_request.endpoint.claimed_id
|
|
50
|
+
which might be different from what you get at the end of the transaction,
|
|
51
|
+
since it is now possible for users to enter their server's url directly.
|
|
52
|
+
|
|
53
|
+
Arguments on the return_to URL are now verified, so if you want to add
|
|
54
|
+
additional arguments to the return_to url, use
|
|
55
|
+
openid_request.return_to_args['param'] = value
|
|
56
|
+
|
|
57
|
+
Generating the redirect is the same as before, but add any extensions
|
|
58
|
+
first.
|
|
59
|
+
|
|
60
|
+
If you need to set up an SSL certificate authority list for the fetcher,
|
|
61
|
+
use the 'ca_file' attr_accessor on the OpenID::StandardFetcher. This has
|
|
62
|
+
changed from 'ca_path' in the 1.x.x series library. That is, set
|
|
63
|
+
OpenID.fetcher.ca_file = '/path/to/ca.list'
|
|
64
|
+
before calling consumer.begin.
|
|
65
|
+
|
|
66
|
+
=== Requesting Simple Registration Data
|
|
67
|
+
|
|
68
|
+
You'll need to require the code for the extension
|
|
69
|
+
require 'openid/extensions/sreg'
|
|
70
|
+
|
|
71
|
+
The new code for adding an SReg request now looks like:
|
|
72
|
+
|
|
73
|
+
sreg_request = OpenID::SReg::Request.new
|
|
74
|
+
sreg_request.request_fields(['email', 'dob'], true) # required
|
|
75
|
+
sreg_request.request_fields(['nickname', 'fullname'], false) # optional
|
|
76
|
+
sreg_request.policy_url = policy_url
|
|
77
|
+
openid_request.add_extension(sreg_request)
|
|
78
|
+
|
|
79
|
+
The code for adding other extensions is similar. Code for the Attribute
|
|
80
|
+
Exchange (AX) and Provider Authentication Policy Extension (PAPE) are
|
|
81
|
+
included with the library, and additional extensions can be implemented
|
|
82
|
+
subclassing OpenID::Extension.
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
=== Completing the transaction
|
|
86
|
+
|
|
87
|
+
The return_to and its arguments are verified, so you need to pass in
|
|
88
|
+
the base URL and the arguments. With Rails, the params method mashes
|
|
89
|
+
together parameters from GET, POST, and the path, so you'll need to pull
|
|
90
|
+
off the path "parameters" with something like
|
|
91
|
+
|
|
92
|
+
return_to = url_for(:only_path => false,
|
|
93
|
+
:controller => 'openid',
|
|
94
|
+
:action => 'complete')
|
|
95
|
+
parameters = params.reject{|k,v| request.path_parameters[k] }
|
|
96
|
+
openid_response = consumer.complete(parameters, return_to)
|
|
97
|
+
|
|
98
|
+
The response still uses the status codes, but they are now namespaced
|
|
99
|
+
slightly differently, for example OpenID::Consumer::SUCCESS
|
|
100
|
+
|
|
101
|
+
In the case of failure, the error message is now found in
|
|
102
|
+
openid_response.message
|
|
103
|
+
|
|
104
|
+
The identifier to display to the user can be found in
|
|
105
|
+
openid_response.endpoint.display_identifier
|
|
106
|
+
|
|
107
|
+
The Simple Registration response can be read from the OpenID response
|
|
108
|
+
with
|
|
109
|
+
sreg_response = OpenID::SReg::Response.from_success_response(openid_response)
|
|
110
|
+
nickname = sreg_response['nickname']
|
|
111
|
+
# etc.
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
== Server Upgrade
|
|
115
|
+
|
|
116
|
+
The server code is mostly the same as before, with the exception of
|
|
117
|
+
extensions. Also, you must pass in the endpoint URL to the server
|
|
118
|
+
constructor:
|
|
119
|
+
@server = OpenID::Server.new(store, server_url)
|
|
120
|
+
|
|
121
|
+
I recommend looking at
|
|
122
|
+
examples/rails_openid/app/controllers/server_controller.rb
|
|
123
|
+
for an example of the new way of doing extensions.
|
|
124
|
+
|
|
125
|
+
--
|
|
126
|
+
Dag Arneson, JanRain Inc.
|
|
127
|
+
Please direct questions to openid@janrain.com
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.1.8
|
data/examples/README
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
This directory contains several examples that demonstrate use of the
|
|
2
|
+
OpenID library. Make sure you have properly installed the library
|
|
3
|
+
before running the examples. These examples are a great place to
|
|
4
|
+
start in integrating OpenID into your application.
|
|
5
|
+
|
|
6
|
+
==Rails example
|
|
7
|
+
|
|
8
|
+
The rails_openid contains a fully functional OpenID server and relying
|
|
9
|
+
party, and acts as a starting point for implementing your own
|
|
10
|
+
production rails server. You'll need the latest version of Ruby on
|
|
11
|
+
Rails installed, and then:
|
|
12
|
+
|
|
13
|
+
cd rails_openid
|
|
14
|
+
./script/server
|
|
15
|
+
|
|
16
|
+
Open a web browser to http://localhost:3000/ and follow the instructions.
|
|
17
|
+
|
|
18
|
+
The relevant code to work from when writing your Rails OpenID Relying
|
|
19
|
+
Party is:
|
|
20
|
+
rails_openid/app/controllers/consumer_controller.rb
|
|
21
|
+
If you are working on an OpenID provider, check out
|
|
22
|
+
rails_openid/app/controllers/server_controller.rb
|
|
23
|
+
|
|
24
|
+
Since the library and examples are Apache-licensed, don't be shy about
|
|
25
|
+
copy-and-paste.
|
|
26
|
+
|
|
27
|
+
==Rails ActiveRecord OpenIDStore plugin
|
|
28
|
+
|
|
29
|
+
For various reasons you may want or need to deploy your ruby openid
|
|
30
|
+
consumer/server using an SQL based store. The active_record_openid_store
|
|
31
|
+
is a plugin that makes using an SQL based store simple. Follow the
|
|
32
|
+
README inside the plugin's dir for usage.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
=Active Record OpenID Store Plugin
|
|
2
|
+
|
|
3
|
+
A store is required by an OpenID server and optionally by the consumer
|
|
4
|
+
to store associations, nonces, and auth key information across
|
|
5
|
+
requests and processes. If rails is distributed across several
|
|
6
|
+
machines, they must must all have access to the same OpenID store
|
|
7
|
+
data, so the FilesystemStore won't do.
|
|
8
|
+
|
|
9
|
+
This directory contains a plugin for connecting your
|
|
10
|
+
OpenID enabled rails app to an ActiveRecord based OpenID store.
|
|
11
|
+
|
|
12
|
+
==Install
|
|
13
|
+
|
|
14
|
+
1) Copy this directory and all it's contents into your
|
|
15
|
+
RAILS_ROOT/vendor/plugins directory. You structure should look like
|
|
16
|
+
this:
|
|
17
|
+
|
|
18
|
+
RAILS_ROOT/vendor/plugins/active_record_openid_store/
|
|
19
|
+
|
|
20
|
+
2) Copy the migration, XXX_add_open_id_store_to_db.rb to your
|
|
21
|
+
RAILS_ROOT/db/migrate directory. Rename the XXX portion of the
|
|
22
|
+
file to next sequential migration number.
|
|
23
|
+
|
|
24
|
+
3) Run the migration:
|
|
25
|
+
|
|
26
|
+
rake migrate
|
|
27
|
+
|
|
28
|
+
4) Change your app to use the ActiveRecordOpenIDStore:
|
|
29
|
+
|
|
30
|
+
store = ActiveRecordOpenIDStore.new
|
|
31
|
+
consumer = OpenID::Consumer.new(session, store)
|
|
32
|
+
|
|
33
|
+
5) That's it! All your OpenID state will now be stored in the database.
|
|
34
|
+
|
|
35
|
+
==Upgrade
|
|
36
|
+
|
|
37
|
+
If you are upgrading from the 1.x ActiveRecord store, replace your old
|
|
38
|
+
RAILS_ROOT/vendor/plugins/active_record_openid_store/ directory with
|
|
39
|
+
the new one and run the migration XXX_upgrade_open_id_store.rb.
|
|
40
|
+
|
|
41
|
+
==What about garbage collection?
|
|
42
|
+
|
|
43
|
+
You may garbage collect unused nonces and expired associations using
|
|
44
|
+
the gc instance method of ActiveRecordOpenIDStore. Hook it up to a
|
|
45
|
+
task in your app's Rakefile like so:
|
|
46
|
+
|
|
47
|
+
desc 'GC OpenID store'
|
|
48
|
+
task :gc_openid_store => :environment do
|
|
49
|
+
ActiveRecordOpenIDStore.new.cleanup
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
Run it by typing:
|
|
53
|
+
|
|
54
|
+
rake gc_openid_store
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
==Questions?
|
|
58
|
+
Contact Dag Arneson: dag at janrain dot com
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Use this migration to create the tables for the ActiveRecord store
|
|
2
|
+
class AddOpenIdStoreToDb < ActiveRecord::Migration
|
|
3
|
+
def self.up
|
|
4
|
+
create_table "open_id_associations", :force => true do |t|
|
|
5
|
+
t.column "server_url", :binary, :null => false
|
|
6
|
+
t.column "handle", :string, :null => false
|
|
7
|
+
t.column "secret", :binary, :null => false
|
|
8
|
+
t.column "issued", :integer, :null => false
|
|
9
|
+
t.column "lifetime", :integer, :null => false
|
|
10
|
+
t.column "assoc_type", :string, :null => false
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
create_table "open_id_nonces", :force => true do |t|
|
|
14
|
+
t.column :server_url, :string, :null => false
|
|
15
|
+
t.column :timestamp, :integer, :null => false
|
|
16
|
+
t.column :salt, :string, :null => false
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.down
|
|
21
|
+
drop_table "open_id_associations"
|
|
22
|
+
drop_table "open_id_nonces"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Use this migration to upgrade the old 1.1 ActiveRecord store schema
|
|
2
|
+
# to the new 2.0 schema.
|
|
3
|
+
class UpgradeOpenIdStore < ActiveRecord::Migration
|
|
4
|
+
def self.up
|
|
5
|
+
drop_table "open_id_settings"
|
|
6
|
+
drop_table "open_id_nonces"
|
|
7
|
+
create_table "open_id_nonces", :force => true do |t|
|
|
8
|
+
t.column :server_url, :string, :null => false
|
|
9
|
+
t.column :timestamp, :integer, :null => false
|
|
10
|
+
t.column :salt, :string, :null => false
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.down
|
|
15
|
+
drop_table "open_id_nonces"
|
|
16
|
+
create_table "open_id_nonces", :force => true do |t|
|
|
17
|
+
t.column "nonce", :string
|
|
18
|
+
t.column "created", :integer
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
create_table "open_id_settings", :force => true do |t|
|
|
22
|
+
t.column "setting", :string
|
|
23
|
+
t.column "value", :binary
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'association'
|
|
2
|
+
require 'nonce'
|
|
3
|
+
require 'openid/store/interface'
|
|
4
|
+
|
|
5
|
+
# not in OpenID module to avoid namespace conflict
|
|
6
|
+
class ActiveRecordStore < OpenID::Store::Interface
|
|
7
|
+
def store_association(server_url, assoc)
|
|
8
|
+
remove_association(server_url, assoc.handle)
|
|
9
|
+
Association.create!(:server_url => server_url,
|
|
10
|
+
:handle => assoc.handle,
|
|
11
|
+
:secret => assoc.secret,
|
|
12
|
+
:issued => assoc.issued.to_i,
|
|
13
|
+
:lifetime => assoc.lifetime,
|
|
14
|
+
:assoc_type => assoc.assoc_type)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def get_association(server_url, handle=nil)
|
|
18
|
+
assocs = if handle.blank?
|
|
19
|
+
Association.find_all_by_server_url(server_url)
|
|
20
|
+
else
|
|
21
|
+
Association.find_all_by_server_url_and_handle(server_url, handle)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
assocs.reverse.each do |assoc|
|
|
25
|
+
a = assoc.from_record
|
|
26
|
+
if a.expires_in == 0
|
|
27
|
+
assoc.destroy
|
|
28
|
+
else
|
|
29
|
+
return a
|
|
30
|
+
end
|
|
31
|
+
end if assocs.any?
|
|
32
|
+
|
|
33
|
+
return nil
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def remove_association(server_url, handle)
|
|
37
|
+
Association.delete_all(['server_url = ? AND handle = ?', server_url, handle]) > 0
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def use_nonce(server_url, timestamp, salt)
|
|
41
|
+
return false if Nonce.find_by_server_url_and_timestamp_and_salt(server_url, timestamp, salt)
|
|
42
|
+
return false if (timestamp - Time.now.to_i).abs > OpenID::Nonce.skew
|
|
43
|
+
Nonce.create!(:server_url => server_url, :timestamp => timestamp, :salt => salt)
|
|
44
|
+
return true
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def cleanup_nonces
|
|
48
|
+
now = Time.now.to_i
|
|
49
|
+
Nonce.delete_all(["timestamp > ? OR timestamp < ?", now + OpenID::Nonce.skew, now - OpenID::Nonce.skew])
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def cleanup_associations
|
|
53
|
+
now = Time.now.to_i
|
|
54
|
+
Association.delete_all(['issued + lifetime > ?',now])
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end
|
|
@@ -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/examples/discover
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require "openid/consumer/discovery"
|
|
3
|
+
require 'openid/fetchers'
|
|
4
|
+
|
|
5
|
+
OpenID::fetcher_use_env_http_proxy
|
|
6
|
+
|
|
7
|
+
$names = [[:server_url, "Server URL "],
|
|
8
|
+
[:local_id, "Local ID "],
|
|
9
|
+
[:canonical_id, "Canonical ID"],
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
def show_services(user_input, normalized, services)
|
|
13
|
+
puts " Claimed identifier: #{normalized}"
|
|
14
|
+
if services.empty?
|
|
15
|
+
puts " No OpenID services found"
|
|
16
|
+
puts
|
|
17
|
+
else
|
|
18
|
+
puts " Discovered services:"
|
|
19
|
+
n = 0
|
|
20
|
+
services.each do |service|
|
|
21
|
+
n += 1
|
|
22
|
+
puts " #{n}."
|
|
23
|
+
$names.each do |meth, name|
|
|
24
|
+
val = service.send(meth)
|
|
25
|
+
if val
|
|
26
|
+
printf(" %s: %s\n", name, val)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
puts " Type URIs:"
|
|
30
|
+
for type_uri in service.type_uris
|
|
31
|
+
puts " * #{type_uri}"
|
|
32
|
+
end
|
|
33
|
+
puts
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
ARGV.each do |openid_identifier|
|
|
39
|
+
puts "=" * 50
|
|
40
|
+
puts "Running discovery on #{openid_identifier}"
|
|
41
|
+
begin
|
|
42
|
+
normalized_identifier, services = OpenID.discover(openid_identifier)
|
|
43
|
+
rescue OpenID::DiscoveryFailure => why
|
|
44
|
+
puts "Discovery failed: #{why.message}"
|
|
45
|
+
puts
|
|
46
|
+
else
|
|
47
|
+
show_services(openid_identifier, normalized_identifier, services)
|
|
48
|
+
end
|
|
49
|
+
end
|