ruby-openid 1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ruby-openid might be problematic. Click here for more details.

Files changed (114) hide show
  1. data/COPYING +21 -0
  2. data/INSTALL +34 -0
  3. data/README +67 -0
  4. data/TODO +9 -0
  5. data/examples/README +54 -0
  6. data/examples/cacert.pem +7815 -0
  7. data/examples/consumer.rb +285 -0
  8. data/examples/openid-store/associations/http-localhost_3A3000_2Fserver-EMQbAy3NnHVzA.s0u5KAcplKGzo +6 -0
  9. data/examples/openid-store/auth_key +1 -0
  10. data/examples/rails_active_record_store/README +59 -0
  11. data/examples/rails_active_record_store/XX_add_openidstore.rb +30 -0
  12. data/examples/rails_active_record_store/models/openid_association.rb +12 -0
  13. data/examples/rails_active_record_store/models/openid_nonce.rb +3 -0
  14. data/examples/rails_active_record_store/models/openid_setting.rb +2 -0
  15. data/examples/rails_active_record_store/openid_helper.rb +91 -0
  16. data/examples/rails_active_record_store/openidstore_test.rb +15 -0
  17. data/examples/rails_active_record_store/schema.mysql.sql +22 -0
  18. data/examples/rails_active_record_store/schema.postgresql.sql +21 -0
  19. data/examples/rails_active_record_store/schema.sqlite.sql +21 -0
  20. data/examples/rails_openid_login_generator/USAGE +23 -0
  21. data/examples/rails_openid_login_generator/openid_login_generator.rb +36 -0
  22. data/examples/rails_openid_login_generator/templates/README +116 -0
  23. data/examples/rails_openid_login_generator/templates/controller.rb +116 -0
  24. data/examples/rails_openid_login_generator/templates/controller_test.rb +0 -0
  25. data/examples/rails_openid_login_generator/templates/helper.rb +2 -0
  26. data/examples/rails_openid_login_generator/templates/openid_login_system.rb +87 -0
  27. data/examples/rails_openid_login_generator/templates/user.rb +14 -0
  28. data/examples/rails_openid_login_generator/templates/user_test.rb +0 -0
  29. data/examples/rails_openid_login_generator/templates/users.yml +0 -0
  30. data/examples/rails_openid_login_generator/templates/view_login.rhtml +15 -0
  31. data/examples/rails_openid_login_generator/templates/view_logout.rhtml +10 -0
  32. data/examples/rails_openid_login_generator/templates/view_welcome.rhtml +9 -0
  33. data/examples/rails_server/README +153 -0
  34. data/examples/rails_server/Rakefile +10 -0
  35. data/examples/rails_server/app/controllers/application.rb +4 -0
  36. data/examples/rails_server/app/controllers/login_controller.rb +35 -0
  37. data/examples/rails_server/app/controllers/server_controller.rb +185 -0
  38. data/examples/rails_server/app/helpers/application_helper.rb +3 -0
  39. data/examples/rails_server/app/helpers/login_helper.rb +2 -0
  40. data/examples/rails_server/app/helpers/server_helper.rb +9 -0
  41. data/examples/rails_server/app/views/layouts/server.rhtml +61 -0
  42. data/examples/rails_server/app/views/login/index.rhtml +32 -0
  43. data/examples/rails_server/app/views/server/decide.rhtml +11 -0
  44. data/examples/rails_server/config/boot.rb +19 -0
  45. data/examples/rails_server/config/database.yml +85 -0
  46. data/examples/rails_server/config/environment.rb +53 -0
  47. data/examples/rails_server/config/environments/development.rb +19 -0
  48. data/examples/rails_server/config/environments/production.rb +19 -0
  49. data/examples/rails_server/config/environments/test.rb +19 -0
  50. data/examples/rails_server/config/routes.rb +23 -0
  51. data/examples/rails_server/db/openid-store/associations/http-localhost_2F_7Cnormal-YU.tkND1J4fEZhnuAoT5Zc0yCA0 +6 -0
  52. data/examples/rails_server/doc/README_FOR_APP +2 -0
  53. data/examples/rails_server/log/development.log +6059 -0
  54. data/examples/rails_server/log/production.log +0 -0
  55. data/examples/rails_server/log/server.log +0 -0
  56. data/examples/rails_server/log/test.log +0 -0
  57. data/examples/rails_server/public/404.html +8 -0
  58. data/examples/rails_server/public/500.html +8 -0
  59. data/examples/rails_server/public/dispatch.cgi +12 -0
  60. data/examples/rails_server/public/dispatch.fcgi +26 -0
  61. data/examples/rails_server/public/dispatch.rb +12 -0
  62. data/examples/rails_server/public/favicon.ico +0 -0
  63. data/examples/rails_server/public/images/rails.png +0 -0
  64. data/examples/rails_server/public/javascripts/controls.js +750 -0
  65. data/examples/rails_server/public/javascripts/dragdrop.js +584 -0
  66. data/examples/rails_server/public/javascripts/effects.js +854 -0
  67. data/examples/rails_server/public/javascripts/prototype.js +1785 -0
  68. data/examples/rails_server/public/robots.txt +1 -0
  69. data/examples/rails_server/script/about +3 -0
  70. data/examples/rails_server/script/breakpointer +3 -0
  71. data/examples/rails_server/script/console +3 -0
  72. data/examples/rails_server/script/destroy +3 -0
  73. data/examples/rails_server/script/generate +3 -0
  74. data/examples/rails_server/script/performance/benchmarker +3 -0
  75. data/examples/rails_server/script/performance/profiler +3 -0
  76. data/examples/rails_server/script/plugin +3 -0
  77. data/examples/rails_server/script/process/reaper +3 -0
  78. data/examples/rails_server/script/process/spawner +3 -0
  79. data/examples/rails_server/script/process/spinner +3 -0
  80. data/examples/rails_server/script/runner +3 -0
  81. data/examples/rails_server/script/server +3 -0
  82. data/examples/rails_server/test/functional/login_controller_test.rb +18 -0
  83. data/examples/rails_server/test/functional/server_controller_test.rb +18 -0
  84. data/examples/rails_server/test/test_helper.rb +28 -0
  85. data/lib/hmac-md5.rb +11 -0
  86. data/lib/hmac-rmd160.rb +11 -0
  87. data/lib/hmac-sha1.rb +11 -0
  88. data/lib/hmac-sha2.rb +25 -0
  89. data/lib/hmac.rb +112 -0
  90. data/lib/openid/association.rb +109 -0
  91. data/lib/openid/consumer.rb +928 -0
  92. data/lib/openid/dh.rb +48 -0
  93. data/lib/openid/discovery.rb +89 -0
  94. data/lib/openid/fetchers.rb +119 -0
  95. data/lib/openid/filestore.rb +315 -0
  96. data/lib/openid/htmltokenizer.rb +355 -0
  97. data/lib/openid/parse.rb +23 -0
  98. data/lib/openid/server.rb +951 -0
  99. data/lib/openid/service.rb +135 -0
  100. data/lib/openid/stores.rb +178 -0
  101. data/lib/openid/trustroot.rb +100 -0
  102. data/lib/openid/util.rb +273 -0
  103. data/test/assoc.rb +38 -0
  104. data/test/consumer.rb +384 -0
  105. data/test/dh.rb +20 -0
  106. data/test/extensions.rb +30 -0
  107. data/test/linkparse.rb +305 -0
  108. data/test/runtests.rb +11 -0
  109. data/test/server2.rb +1053 -0
  110. data/test/storetestcase.rb +172 -0
  111. data/test/teststore.rb +23 -0
  112. data/test/trustroot.rb +113 -0
  113. data/test/util.rb +56 -0
  114. metadata +218 -0
@@ -0,0 +1,14 @@
1
+
2
+ # this model expects a certain database layout and its based on the name/login pattern.
3
+ class User < ActiveRecord::Base
4
+
5
+ def self.get(openid_url)
6
+ find_first(["openid_url = ?", openid_url])
7
+ end
8
+
9
+
10
+ protected
11
+
12
+ validates_uniqueness_of :openid_url, :on => :create
13
+ validates_presence_of :openid_url
14
+ end
@@ -0,0 +1,15 @@
1
+ <%%= start_form_tag :action=> "login" %>
2
+
3
+ <div title="Account login" id="loginform" class="form">
4
+ <h3>Please login</h3>
5
+
6
+ <label for="user_login">Login:</label><br/>
7
+ <input type="text" name="openid_url" id="openid_url" size="30" value="<%= @login %>"/><br/>
8
+
9
+ <br/>
10
+ <input type="submit" name="login" value="Login &#187;" class="primary" />
11
+
12
+ </div>
13
+
14
+ <%%= end_form_tag %>
15
+
@@ -0,0 +1,10 @@
1
+
2
+ <div class="memo">
3
+ <h3>Logoff</h3>
4
+
5
+ <p>You are now logged out of the system...</p>
6
+
7
+ <%%= link_to "&#171; login", :action=>"login"%>
8
+
9
+ </div>
10
+
@@ -0,0 +1,9 @@
1
+
2
+ <div class="memo">
3
+ <h3>Welcome</h3>
4
+
5
+ <p>You are now logged into the system...</p>
6
+
7
+ <%%= link_to "&#171; logout", :action=>"logout"%>
8
+
9
+ </div>
@@ -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,35 @@
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
+ class LoginController < ApplicationController
5
+
6
+ layout 'server'
7
+
8
+ def index
9
+ # just show the login page
10
+ end
11
+
12
+ def submit
13
+ user = @params[:username]
14
+
15
+ # if we get a user, log them in by putting their username in
16
+ # the session hash.
17
+ unless user.nil?
18
+ session[:username] = user unless user.nil?
19
+ session[:approvals] = []
20
+ flash[:notice] = "Your OpenID URL is <b>http://localhost:3000/user/#{user}</b><br/><br/>Proceed to step 2 below."
21
+ else
22
+ flash[:error] = "Sorry, couldn't log you in. Try again."
23
+ end
24
+
25
+ redirect_to :action => 'index'
26
+ end
27
+
28
+ def logout
29
+ # delete the username from the session hash
30
+ session[:username] = nil
31
+ session[:approvals] = nil
32
+ redirect_to :action => 'index'
33
+ end
34
+
35
+ end
@@ -0,0 +1,185 @@
1
+ require 'pathname'
2
+
3
+ require 'openid/filestore'
4
+ require 'openid/server'
5
+
6
+ class ServerController < ApplicationController
7
+
8
+ include ServerHelper
9
+ include OpenID::Server
10
+ layout nil
11
+
12
+ def index
13
+ begin
14
+ request = server.decode_request(@params)
15
+ rescue ProtocolError => e
16
+ # invalid openid request, so just display a page with an error message
17
+ render_text e.to_s
18
+ return
19
+ end
20
+
21
+ # no openid.mode was given
22
+ unless request
23
+ render_text "This is an OpenID server endpoint."
24
+ return
25
+ end
26
+
27
+ if request.kind_of?(CheckIDRequest)
28
+
29
+ if self.is_authorized(request.identity_url, request.trust_root)
30
+ response = request.answer(true)
31
+
32
+ # add the sreg response if requested
33
+ self.add_sreg(request, response)
34
+
35
+ elsif request.immediate
36
+ server_url = url_for :action => 'index'
37
+ response = request.answer(false, server_url)
38
+
39
+ else
40
+ @session[:last_request] = request
41
+ @request = request
42
+ flash[:notice] = "Do you trust this site with your identity?"
43
+ render :template => 'server/decide', :layout => 'server'
44
+ return
45
+ end
46
+
47
+ else
48
+ response = server.handle_request(request)
49
+ end
50
+
51
+ self.render_response(response)
52
+ end
53
+
54
+ def user_page
55
+ # Yadis content-negotiation: we want to return the xrds if asked for.
56
+ accept = request.env['HTTP_ACCEPT']
57
+
58
+ # This is not technically correct, and should eventually be updated
59
+ # to do real Accept header parsing and logic. Though I expect it will work
60
+ # 99% of the time.
61
+ if accept and accept.include?('application/xrds+xml')
62
+ render_xrds
63
+ return
64
+ end
65
+
66
+ # content negotiation failed, so just render the user page
67
+ xrds_url = url_for(:controller=>'user',:action=>@params[:username])+'/xrds'
68
+ identity_page = <<EOS
69
+ <html><head>
70
+ <meta http-equiv="X-XRDS-Location" content="#{xrds_url}" />
71
+ <link rel="openid.server" href="#{url_for :action => 'index'}" />
72
+ </head><body><p>OpenID identity page for #{@params[:username]}</p>
73
+ </body></html>
74
+ EOS
75
+
76
+ # Also add the Yadis location header, so that they don't have
77
+ # to parse the html unless absolutely necessary.
78
+ response.headers['X-XRDS-Location'] = xrds_url
79
+ render_text identity_page
80
+ end
81
+
82
+ def xrds
83
+ render_xrds
84
+ end
85
+
86
+ def decision
87
+ request = @session[:last_request]
88
+ @session[:last_request] = nil
89
+
90
+ if @params[:yes].nil?
91
+ redirect_to request.cancel_url
92
+ return
93
+ else
94
+ session[:approvals] << request.trust_root
95
+ response = request.answer(true)
96
+ self.add_sreg(request, response)
97
+ return self.render_response(response)
98
+ end
99
+ end
100
+
101
+ protected
102
+
103
+ def server
104
+ if @server.nil?
105
+ dir = Pathname.new(RAILS_ROOT).join('db').join('openid-store')
106
+ store = OpenID::FilesystemStore.new(dir)
107
+ @server = Server.new(store)
108
+ end
109
+ return @server
110
+ end
111
+
112
+ def approved(trust_root)
113
+ return false if session[:approvals].nil?
114
+ return session[:approvals].member?(trust_root)
115
+ end
116
+
117
+ def is_authorized(identity_url, trust_root)
118
+ return (session[:username] and (identity_url == url_for_user) and self.approved(trust_root))
119
+ end
120
+
121
+ def render_xrds
122
+ yadis = <<EOS
123
+ <?xml version="1.0" encoding="UTF-8"?>
124
+ <xrds:XRDS
125
+ xmlns:xrds="xri://$xrds"
126
+ xmlns:openid="http://openid.net/xmlns/1.0"
127
+ xmlns="xri://$xrd*($v*2.0)">
128
+ <XRD>
129
+ <Service priority="1">
130
+ <Type>http://openid.net/signon/1.0</Type>
131
+ <Type>http://openid.net/sreg/1.0</Type>
132
+ <URI>#{url_for(:controller => 'server')}</URI>
133
+ </Service>
134
+ </XRD>
135
+ </xrds:XRDS>
136
+ EOS
137
+
138
+ response.headers['content-type'] = 'application/xrds+xml'
139
+ render_text yadis
140
+ end
141
+
142
+ def add_sreg(request, response)
143
+ # Your code should examine request.query
144
+ # for openid.sreg.required, openid.sreg.optional, and
145
+ # openid.sreg.policy_url, and generate add fields to your response
146
+ # accordingly. For this example, we'll just see if there are any
147
+ # sreg args and add some sreg data to the response. Take note,
148
+ # that this does not actually respect the sreg query, it just sends
149
+ # back some fake sreg data. Your implemetation should be better! :)
150
+
151
+ required = request.query['openid.sreg.required']
152
+ optional = request.query['openid.sreg.optional']
153
+ policy_url = request.query['openid.sreg.policy_url']
154
+
155
+ if required or optional or policy_url
156
+ # this should be taken out of the user's profile,
157
+ # but since we don't have one lets just make up some data.
158
+ # Also, the user should be able to approve the transfer
159
+ # and modify each field if she likes.
160
+ sreg_fields = {
161
+ 'email' => 'mayor@example.com',
162
+ 'nickname' => 'Mayor McCheese'
163
+ }
164
+ response.add_fields('sreg', sreg_fields)
165
+ end
166
+
167
+ end
168
+
169
+ def render_response(response)
170
+ web_response = server.encode_response(response)
171
+
172
+ case web_response.code
173
+ when HTTP_OK
174
+ render_text web_response.body, :status => 200
175
+
176
+ when HTTP_REDIRECT
177
+ redirect_to web_response.redirect_url
178
+
179
+ else
180
+ render_text web_response.body, :status => 400
181
+ end
182
+ end
183
+
184
+
185
+ end