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.
Files changed (197) hide show
  1. data/CHANGELOG +215 -0
  2. data/CHANGES-2.1.0 +36 -0
  3. data/INSTALL +47 -0
  4. data/LICENSE +210 -0
  5. data/NOTICE +2 -0
  6. data/README +82 -0
  7. data/UPGRADE +127 -0
  8. data/VERSION +1 -0
  9. data/examples/README +32 -0
  10. data/examples/active_record_openid_store/README +58 -0
  11. data/examples/active_record_openid_store/XXX_add_open_id_store_to_db.rb +24 -0
  12. data/examples/active_record_openid_store/XXX_upgrade_open_id_store.rb +26 -0
  13. data/examples/active_record_openid_store/init.rb +8 -0
  14. data/examples/active_record_openid_store/lib/association.rb +10 -0
  15. data/examples/active_record_openid_store/lib/nonce.rb +3 -0
  16. data/examples/active_record_openid_store/lib/open_id_setting.rb +4 -0
  17. data/examples/active_record_openid_store/lib/openid_ar_store.rb +57 -0
  18. data/examples/active_record_openid_store/test/store_test.rb +212 -0
  19. data/examples/discover +49 -0
  20. data/examples/rails_openid/README +153 -0
  21. data/examples/rails_openid/Rakefile +10 -0
  22. data/examples/rails_openid/app/controllers/application.rb +4 -0
  23. data/examples/rails_openid/app/controllers/consumer_controller.rb +122 -0
  24. data/examples/rails_openid/app/controllers/login_controller.rb +45 -0
  25. data/examples/rails_openid/app/controllers/server_controller.rb +265 -0
  26. data/examples/rails_openid/app/helpers/application_helper.rb +3 -0
  27. data/examples/rails_openid/app/helpers/login_helper.rb +2 -0
  28. data/examples/rails_openid/app/helpers/server_helper.rb +9 -0
  29. data/examples/rails_openid/app/views/consumer/index.rhtml +81 -0
  30. data/examples/rails_openid/app/views/layouts/server.rhtml +68 -0
  31. data/examples/rails_openid/app/views/login/index.rhtml +56 -0
  32. data/examples/rails_openid/app/views/server/decide.rhtml +26 -0
  33. data/examples/rails_openid/config/boot.rb +19 -0
  34. data/examples/rails_openid/config/database.yml +74 -0
  35. data/examples/rails_openid/config/environment.rb +54 -0
  36. data/examples/rails_openid/config/environments/development.rb +19 -0
  37. data/examples/rails_openid/config/environments/production.rb +19 -0
  38. data/examples/rails_openid/config/environments/test.rb +19 -0
  39. data/examples/rails_openid/config/routes.rb +24 -0
  40. data/examples/rails_openid/doc/README_FOR_APP +2 -0
  41. data/examples/rails_openid/public/.htaccess +40 -0
  42. data/examples/rails_openid/public/404.html +8 -0
  43. data/examples/rails_openid/public/500.html +8 -0
  44. data/examples/rails_openid/public/dispatch.cgi +12 -0
  45. data/examples/rails_openid/public/dispatch.fcgi +26 -0
  46. data/examples/rails_openid/public/dispatch.rb +12 -0
  47. data/examples/rails_openid/public/favicon.ico +0 -0
  48. data/examples/rails_openid/public/images/openid_login_bg.gif +0 -0
  49. data/examples/rails_openid/public/javascripts/controls.js +750 -0
  50. data/examples/rails_openid/public/javascripts/dragdrop.js +584 -0
  51. data/examples/rails_openid/public/javascripts/effects.js +854 -0
  52. data/examples/rails_openid/public/javascripts/prototype.js +1785 -0
  53. data/examples/rails_openid/public/robots.txt +1 -0
  54. data/examples/rails_openid/script/about +3 -0
  55. data/examples/rails_openid/script/breakpointer +3 -0
  56. data/examples/rails_openid/script/console +3 -0
  57. data/examples/rails_openid/script/destroy +3 -0
  58. data/examples/rails_openid/script/generate +3 -0
  59. data/examples/rails_openid/script/performance/benchmarker +3 -0
  60. data/examples/rails_openid/script/performance/profiler +3 -0
  61. data/examples/rails_openid/script/plugin +3 -0
  62. data/examples/rails_openid/script/process/reaper +3 -0
  63. data/examples/rails_openid/script/process/spawner +3 -0
  64. data/examples/rails_openid/script/process/spinner +3 -0
  65. data/examples/rails_openid/script/runner +3 -0
  66. data/examples/rails_openid/script/server +3 -0
  67. data/examples/rails_openid/test/functional/login_controller_test.rb +18 -0
  68. data/examples/rails_openid/test/functional/server_controller_test.rb +18 -0
  69. data/examples/rails_openid/test/test_helper.rb +28 -0
  70. data/lib/hmac/hmac.rb +112 -0
  71. data/lib/hmac/sha1.rb +11 -0
  72. data/lib/hmac/sha2.rb +25 -0
  73. data/lib/openid/association.rb +249 -0
  74. data/lib/openid/consumer/associationmanager.rb +344 -0
  75. data/lib/openid/consumer/checkid_request.rb +186 -0
  76. data/lib/openid/consumer/discovery.rb +498 -0
  77. data/lib/openid/consumer/discovery_manager.rb +123 -0
  78. data/lib/openid/consumer/html_parse.rb +134 -0
  79. data/lib/openid/consumer/idres.rb +523 -0
  80. data/lib/openid/consumer/responses.rb +148 -0
  81. data/lib/openid/consumer.rb +395 -0
  82. data/lib/openid/cryptutil.rb +97 -0
  83. data/lib/openid/dh.rb +89 -0
  84. data/lib/openid/extension.rb +39 -0
  85. data/lib/openid/extensions/ax.rb +516 -0
  86. data/lib/openid/extensions/oauth.rb +91 -0
  87. data/lib/openid/extensions/pape.rb +179 -0
  88. data/lib/openid/extensions/sreg.rb +277 -0
  89. data/lib/openid/extras.rb +11 -0
  90. data/lib/openid/fetchers.rb +238 -0
  91. data/lib/openid/kvform.rb +136 -0
  92. data/lib/openid/kvpost.rb +58 -0
  93. data/lib/openid/message.rb +553 -0
  94. data/lib/openid/protocolerror.rb +8 -0
  95. data/lib/openid/server.rb +1544 -0
  96. data/lib/openid/store/filesystem.rb +271 -0
  97. data/lib/openid/store/interface.rb +75 -0
  98. data/lib/openid/store/memcache.rb +107 -0
  99. data/lib/openid/store/memory.rb +84 -0
  100. data/lib/openid/store/nonce.rb +68 -0
  101. data/lib/openid/trustroot.rb +349 -0
  102. data/lib/openid/urinorm.rb +75 -0
  103. data/lib/openid/util.rb +110 -0
  104. data/lib/openid/yadis/accept.rb +148 -0
  105. data/lib/openid/yadis/constants.rb +21 -0
  106. data/lib/openid/yadis/discovery.rb +153 -0
  107. data/lib/openid/yadis/filters.rb +205 -0
  108. data/lib/openid/yadis/htmltokenizer.rb +305 -0
  109. data/lib/openid/yadis/parsehtml.rb +45 -0
  110. data/lib/openid/yadis/services.rb +42 -0
  111. data/lib/openid/yadis/xrds.rb +155 -0
  112. data/lib/openid/yadis/xri.rb +90 -0
  113. data/lib/openid/yadis/xrires.rb +106 -0
  114. data/lib/openid.rb +20 -0
  115. data/setup.rb +1551 -0
  116. data/test/data/accept.txt +124 -0
  117. data/test/data/dh.txt +29 -0
  118. data/test/data/example-xrds.xml +14 -0
  119. data/test/data/linkparse.txt +587 -0
  120. data/test/data/n2b64 +650 -0
  121. data/test/data/test1-discover.txt +137 -0
  122. data/test/data/test1-parsehtml.txt +152 -0
  123. data/test/data/test_discover/malformed_meta_tag.html +19 -0
  124. data/test/data/test_discover/openid.html +11 -0
  125. data/test/data/test_discover/openid2.html +11 -0
  126. data/test/data/test_discover/openid2_xrds.xml +12 -0
  127. data/test/data/test_discover/openid2_xrds_no_local_id.xml +11 -0
  128. data/test/data/test_discover/openid_1_and_2.html +11 -0
  129. data/test/data/test_discover/openid_1_and_2_xrds.xml +16 -0
  130. data/test/data/test_discover/openid_1_and_2_xrds_bad_delegate.xml +17 -0
  131. data/test/data/test_discover/openid_and_yadis.html +12 -0
  132. data/test/data/test_discover/openid_no_delegate.html +10 -0
  133. data/test/data/test_discover/yadis_0entries.xml +12 -0
  134. data/test/data/test_discover/yadis_2_bad_local_id.xml +15 -0
  135. data/test/data/test_discover/yadis_2entries_delegate.xml +22 -0
  136. data/test/data/test_discover/yadis_2entries_idp.xml +21 -0
  137. data/test/data/test_discover/yadis_another_delegate.xml +14 -0
  138. data/test/data/test_discover/yadis_idp.xml +12 -0
  139. data/test/data/test_discover/yadis_idp_delegate.xml +13 -0
  140. data/test/data/test_discover/yadis_no_delegate.xml +11 -0
  141. data/test/data/test_xrds/=j3h.2007.11.14.xrds +25 -0
  142. data/test/data/test_xrds/README +12 -0
  143. data/test/data/test_xrds/delegated-20060809-r1.xrds +34 -0
  144. data/test/data/test_xrds/delegated-20060809-r2.xrds +34 -0
  145. data/test/data/test_xrds/delegated-20060809.xrds +34 -0
  146. data/test/data/test_xrds/no-xrd.xml +7 -0
  147. data/test/data/test_xrds/not-xrds.xml +2 -0
  148. data/test/data/test_xrds/prefixsometimes.xrds +34 -0
  149. data/test/data/test_xrds/ref.xrds +109 -0
  150. data/test/data/test_xrds/sometimesprefix.xrds +34 -0
  151. data/test/data/test_xrds/spoof1.xrds +25 -0
  152. data/test/data/test_xrds/spoof2.xrds +25 -0
  153. data/test/data/test_xrds/spoof3.xrds +37 -0
  154. data/test/data/test_xrds/status222.xrds +9 -0
  155. data/test/data/test_xrds/subsegments.xrds +58 -0
  156. data/test/data/test_xrds/valid-populated-xrds.xml +39 -0
  157. data/test/data/trustroot.txt +153 -0
  158. data/test/data/urinorm.txt +79 -0
  159. data/test/discoverdata.rb +131 -0
  160. data/test/test_accept.rb +170 -0
  161. data/test/test_association.rb +266 -0
  162. data/test/test_associationmanager.rb +917 -0
  163. data/test/test_ax.rb +648 -0
  164. data/test/test_checkid_request.rb +294 -0
  165. data/test/test_consumer.rb +257 -0
  166. data/test/test_cryptutil.rb +119 -0
  167. data/test/test_dh.rb +86 -0
  168. data/test/test_discover.rb +838 -0
  169. data/test/test_discovery_manager.rb +262 -0
  170. data/test/test_extension.rb +46 -0
  171. data/test/test_extras.rb +35 -0
  172. data/test/test_fetchers.rb +538 -0
  173. data/test/test_filters.rb +270 -0
  174. data/test/test_idres.rb +963 -0
  175. data/test/test_kvform.rb +165 -0
  176. data/test/test_kvpost.rb +65 -0
  177. data/test/test_linkparse.rb +101 -0
  178. data/test/test_message.rb +1116 -0
  179. data/test/test_nonce.rb +89 -0
  180. data/test/test_oauth.rb +175 -0
  181. data/test/test_openid_yadis.rb +178 -0
  182. data/test/test_pape.rb +247 -0
  183. data/test/test_parsehtml.rb +80 -0
  184. data/test/test_responses.rb +63 -0
  185. data/test/test_server.rb +2457 -0
  186. data/test/test_sreg.rb +479 -0
  187. data/test/test_stores.rb +298 -0
  188. data/test/test_trustroot.rb +113 -0
  189. data/test/test_urinorm.rb +35 -0
  190. data/test/test_util.rb +145 -0
  191. data/test/test_xrds.rb +169 -0
  192. data/test/test_xri.rb +48 -0
  193. data/test/test_xrires.rb +63 -0
  194. data/test/test_yadis_discovery.rb +220 -0
  195. data/test/testutil.rb +127 -0
  196. data/test/util.rb +53 -0
  197. metadata +316 -0
@@ -0,0 +1,153 @@
1
+ == Welcome to Rails
2
+
3
+ Rails is a web-application and persistence framework that includes everything
4
+ needed to create database-backed web-applications according to the
5
+ Model-View-Control pattern of separation. This pattern splits the view (also
6
+ called the presentation) into "dumb" templates that are primarily responsible
7
+ for inserting pre-built data in between HTML tags. The model contains the
8
+ "smart" domain objects (such as Account, Product, Person, Post) that holds all
9
+ the business logic and knows how to persist themselves to a database. The
10
+ controller handles the incoming requests (such as Save New Account, Update
11
+ Product, Show Post) by manipulating the model and directing data to the view.
12
+
13
+ In Rails, the model is handled by what's called an object-relational mapping
14
+ layer entitled Active Record. This layer allows you to present the data from
15
+ database rows as objects and embellish these data objects with business logic
16
+ methods. You can read more about Active Record in
17
+ link:files/vendor/rails/activerecord/README.html.
18
+
19
+ The controller and view are handled by the Action Pack, which handles both
20
+ layers by its two parts: Action View and Action Controller. These two layers
21
+ are bundled in a single package due to their heavy interdependence. This is
22
+ unlike the relationship between the Active Record and Action Pack that is much
23
+ more separate. Each of these packages can be used independently outside of
24
+ Rails. You can read more about Action Pack in
25
+ link:files/vendor/rails/actionpack/README.html.
26
+
27
+
28
+ == Getting started
29
+
30
+ 1. Run the WEBrick servlet: <tt>ruby script/server</tt> (run with --help for options)
31
+ ...or if you have lighttpd installed: <tt>ruby script/lighttpd</tt> (it's faster)
32
+ 2. Go to http://localhost:3000/ and get "Congratulations, you've put Ruby on Rails!"
33
+ 3. Follow the guidelines on the "Congratulations, you've put Ruby on Rails!" screen
34
+
35
+
36
+ == Example for Apache conf
37
+
38
+ <VirtualHost *:80>
39
+ ServerName rails
40
+ DocumentRoot /path/application/public/
41
+ ErrorLog /path/application/log/server.log
42
+
43
+ <Directory /path/application/public/>
44
+ Options ExecCGI FollowSymLinks
45
+ AllowOverride all
46
+ Allow from all
47
+ Order allow,deny
48
+ </Directory>
49
+ </VirtualHost>
50
+
51
+ NOTE: Be sure that CGIs can be executed in that directory as well. So ExecCGI
52
+ should be on and ".cgi" should respond. All requests from 127.0.0.1 go
53
+ through CGI, so no Apache restart is necessary for changes. All other requests
54
+ go through FCGI (or mod_ruby), which requires a restart to show changes.
55
+
56
+
57
+ == Debugging Rails
58
+
59
+ Have "tail -f" commands running on both the server.log, production.log, and
60
+ test.log files. Rails will automatically display debugging and runtime
61
+ information to these files. Debugging info will also be shown in the browser
62
+ on requests from 127.0.0.1.
63
+
64
+
65
+ == Breakpoints
66
+
67
+ Breakpoint support is available through the script/breakpointer client. This
68
+ means that you can break out of execution at any point in the code, investigate
69
+ and change the model, AND then resume execution! Example:
70
+
71
+ class WeblogController < ActionController::Base
72
+ def index
73
+ @posts = Post.find_all
74
+ breakpoint "Breaking out from the list"
75
+ end
76
+ end
77
+
78
+ So the controller will accept the action, run the first line, then present you
79
+ with a IRB prompt in the breakpointer window. Here you can do things like:
80
+
81
+ Executing breakpoint "Breaking out from the list" at .../webrick_server.rb:16 in 'breakpoint'
82
+
83
+ >> @posts.inspect
84
+ => "[#<Post:0x14a6be8 @attributes={\"title\"=>nil, \"body\"=>nil, \"id\"=>\"1\"}>,
85
+ #<Post:0x14a6620 @attributes={\"title\"=>\"Rails you know!\", \"body\"=>\"Only ten..\", \"id\"=>\"2\"}>]"
86
+ >> @posts.first.title = "hello from a breakpoint"
87
+ => "hello from a breakpoint"
88
+
89
+ ...and even better is that you can examine how your runtime objects actually work:
90
+
91
+ >> f = @posts.first
92
+ => #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>
93
+ >> f.
94
+ Display all 152 possibilities? (y or n)
95
+
96
+ Finally, when you're ready to resume execution, you press CTRL-D
97
+
98
+
99
+ == Console
100
+
101
+ You can interact with the domain model by starting the console through script/console.
102
+ Here you'll have all parts of the application configured, just like it is when the
103
+ application is running. You can inspect domain models, change values, and save to the
104
+ database. Starting the script without arguments will launch it in the development environment.
105
+ Passing an argument will specify a different environment, like <tt>console production</tt>.
106
+
107
+
108
+ == Description of contents
109
+
110
+ app
111
+ Holds all the code that's specific to this particular application.
112
+
113
+ app/controllers
114
+ Holds controllers that should be named like weblog_controller.rb for
115
+ automated URL mapping. All controllers should descend from
116
+ ActionController::Base.
117
+
118
+ app/models
119
+ Holds models that should be named like post.rb.
120
+ Most models will descend from ActiveRecord::Base.
121
+
122
+ app/views
123
+ Holds the template files for the view that should be named like
124
+ weblog/index.rhtml for the WeblogController#index action. All views use eRuby
125
+ syntax. This directory can also be used to keep stylesheets, images, and so on
126
+ that can be symlinked to public.
127
+
128
+ app/helpers
129
+ Holds view helpers that should be named like weblog_helper.rb.
130
+
131
+ config
132
+ Configuration files for the Rails environment, the routing map, the database, and other dependencies.
133
+
134
+ components
135
+ Self-contained mini-applications that can bundle together controllers, models, and views.
136
+
137
+ lib
138
+ Application specific libraries. Basically, any kind of custom code that doesn't
139
+ belong under controllers, models, or helpers. This directory is in the load path.
140
+
141
+ public
142
+ The directory available for the web server. Contains subdirectories for images, stylesheets,
143
+ and javascripts. Also contains the dispatchers and the default HTML files.
144
+
145
+ script
146
+ Helper scripts for automation and generation.
147
+
148
+ test
149
+ Unit and functional tests along with fixtures.
150
+
151
+ vendor
152
+ External libraries that the application depends on. Also includes the plugins subdirectory.
153
+ This directory is in the load path.
@@ -0,0 +1,10 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/switchtower.rake, and they will automatically be available to Rake.
3
+
4
+ require(File.join(File.dirname(__FILE__), 'config', 'boot'))
5
+
6
+ require 'rake'
7
+ require 'rake/testtask'
8
+ require 'rake/rdoctask'
9
+
10
+ require 'tasks/rails'
@@ -0,0 +1,4 @@
1
+ # Filters added to this controller will be run for all controllers in the application.
2
+ # Likewise, all the methods added will be available for all controllers.
3
+ class ApplicationController < ActionController::Base
4
+ end
@@ -0,0 +1,122 @@
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
+ identifier = params[:openid_identifier]
18
+ if identifier.nil?
19
+ flash[:error] = "Enter an OpenID identifier"
20
+ redirect_to :action => 'index'
21
+ return
22
+ end
23
+ oidreq = consumer.begin(identifier)
24
+ rescue OpenID::OpenIDError => e
25
+ flash[:error] = "Discovery failed for #{identifier}: #{e}"
26
+ redirect_to :action => 'index'
27
+ return
28
+ end
29
+ if params[:use_sreg]
30
+ sregreq = OpenID::SReg::Request.new
31
+ # required fields
32
+ sregreq.request_fields(['email','nickname'], true)
33
+ # optional fields
34
+ sregreq.request_fields(['dob', 'fullname'], false)
35
+ oidreq.add_extension(sregreq)
36
+ oidreq.return_to_args['did_sreg'] = 'y'
37
+ end
38
+ if params[:use_pape]
39
+ papereq = OpenID::PAPE::Request.new
40
+ papereq.add_policy_uri(OpenID::PAPE::AUTH_PHISHING_RESISTANT)
41
+ papereq.max_auth_age = 2*60*60
42
+ oidreq.add_extension(papereq)
43
+ oidreq.return_to_args['did_pape'] = 'y'
44
+ end
45
+ if params[:force_post]
46
+ oidreq.return_to_args['force_post']='x'*2048
47
+ end
48
+ return_to = url_for :action => 'complete', :only_path => false
49
+ realm = url_for :action => 'index', :only_path => false
50
+
51
+ if oidreq.send_redirect?(realm, return_to, params[:immediate])
52
+ redirect_to oidreq.redirect_url(realm, return_to, params[:immediate])
53
+ else
54
+ render :text => oidreq.html_markup(realm, return_to, params[:immediate], {'id' => 'openid_form'})
55
+ end
56
+ end
57
+
58
+ def complete
59
+ # FIXME - url_for some action is not necessarily the current URL.
60
+ current_url = url_for(:action => 'complete', :only_path => false)
61
+ parameters = params.reject{|k,v|request.path_parameters[k]}
62
+ oidresp = consumer.complete(parameters, current_url)
63
+ case oidresp.status
64
+ when OpenID::Consumer::FAILURE
65
+ if oidresp.display_identifier
66
+ flash[:error] = ("Verification of #{oidresp.display_identifier}"\
67
+ " failed: #{oidresp.message}")
68
+ else
69
+ flash[:error] = "Verification failed: #{oidresp.message}"
70
+ end
71
+ when OpenID::Consumer::SUCCESS
72
+ flash[:success] = ("Verification of #{oidresp.display_identifier}"\
73
+ " succeeded.")
74
+ if params[:did_sreg]
75
+ sreg_resp = OpenID::SReg::Response.from_success_response(oidresp)
76
+ sreg_message = "Simple Registration data was requested"
77
+ if sreg_resp.empty?
78
+ sreg_message << ", but none was returned."
79
+ else
80
+ sreg_message << ". The following data were sent:"
81
+ sreg_resp.data.each {|k,v|
82
+ sreg_message << "<br/><b>#{k}</b>: #{v}"
83
+ }
84
+ end
85
+ flash[:sreg_results] = sreg_message
86
+ end
87
+ if params[:did_pape]
88
+ pape_resp = OpenID::PAPE::Response.from_success_response(oidresp)
89
+ pape_message = "A phishing resistant authentication method was requested"
90
+ if pape_resp.auth_policies.member? OpenID::PAPE::AUTH_PHISHING_RESISTANT
91
+ pape_message << ", and the server reported one."
92
+ else
93
+ pape_message << ", but the server did not report one."
94
+ end
95
+ if pape_resp.auth_time
96
+ pape_message << "<br><b>Authentication time:</b> #{pape_resp.auth_time} seconds"
97
+ end
98
+ if pape_resp.nist_auth_level
99
+ pape_message << "<br><b>NIST Auth Level:</b> #{pape_resp.nist_auth_level}"
100
+ end
101
+ flash[:pape_results] = pape_message
102
+ end
103
+ when OpenID::Consumer::SETUP_NEEDED
104
+ flash[:alert] = "Immediate request failed - Setup Needed"
105
+ when OpenID::Consumer::CANCEL
106
+ flash[:alert] = "OpenID transaction cancelled."
107
+ else
108
+ end
109
+ redirect_to :action => 'index'
110
+ end
111
+
112
+ private
113
+
114
+ def consumer
115
+ if @consumer.nil?
116
+ dir = Pathname.new(RAILS_ROOT).join('db').join('cstore')
117
+ store = OpenID::Store::Filesystem.new(dir)
118
+ @consumer = OpenID::Consumer.new(session, store)
119
+ end
120
+ return @consumer
121
+ end
122
+ end
@@ -0,0 +1,45 @@
1
+ # Controller for handling the login, logout process for "users" of our
2
+ # little server. Users have no password. This is just an example.
3
+
4
+ require 'openid'
5
+
6
+ class LoginController < ApplicationController
7
+
8
+ layout 'server'
9
+
10
+ def base_url
11
+ url_for(:controller => 'login', :action => nil, :only_path => false)
12
+ end
13
+
14
+ def index
15
+ response.headers['X-XRDS-Location'] = url_for(:controller => "server",
16
+ :action => "idp_xrds",
17
+ :only_path => false)
18
+ @base_url = base_url
19
+ # just show the login page
20
+ end
21
+
22
+ def submit
23
+ user = params[:username]
24
+
25
+ # if we get a user, log them in by putting their username in
26
+ # the session hash.
27
+ unless user.nil?
28
+ session[:username] = user unless user.nil?
29
+ session[:approvals] = []
30
+ flash[:notice] = "Your OpenID URL is <b>#{base_url}user/#{user}</b><br/><br/>Proceed to step 2 below."
31
+ else
32
+ flash[:error] = "Sorry, couldn't log you in. Try again."
33
+ end
34
+
35
+ redirect_to :action => 'index'
36
+ end
37
+
38
+ def logout
39
+ # delete the username from the session hash
40
+ session[:username] = nil
41
+ session[:approvals] = nil
42
+ redirect_to :action => 'index'
43
+ end
44
+
45
+ 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, :status => 500
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
@@ -0,0 +1,3 @@
1
+ # Methods added to this helper will be available to all templates in the application.
2
+ module ApplicationHelper
3
+ end
@@ -0,0 +1,2 @@
1
+ module LoginHelper
2
+ end
@@ -0,0 +1,9 @@
1
+
2
+ module ServerHelper
3
+
4
+ def url_for_user
5
+ url_for :controller => 'user', :action => session[:username]
6
+ end
7
+
8
+ end
9
+