rack-openid 0.2 → 0.2.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.
File without changes
data/README.rdoc CHANGED
@@ -6,7 +6,8 @@ Provides a more HTTPish API around the ruby-openid library.
6
6
 
7
7
  You trigger an OpenID request similar to HTTP authentication. From your app, return a "401 Unauthorized" and a "WWW-Authenticate" header with the identifier you would like to validate.
8
8
 
9
- On completition, the OpenID response is automatically verified and assigned to env["rack.openid.response"].
9
+ On competition, the OpenID response is automatically verified and assigned to
10
+ <tt>env["rack.openid.response"]</tt>.
10
11
 
11
12
  MyApp = lambda { |env|
12
13
  if resp = env["rack.openid.response"]
@@ -16,7 +17,7 @@ On completition, the OpenID response is automatically verified and assigned to e
16
17
  when :failure
17
18
  ...
18
19
  else
19
- [401, {"WWW-Authenticate" => 'OpenID identity="http://example.com/"'}, []]
20
+ [401, {"WWW-Authenticate" => 'OpenID identifier="http://example.com/"'}, []]
20
21
  end
21
22
  }
22
23
 
data/lib/rack/openid.rb CHANGED
@@ -1,33 +1,33 @@
1
1
  require 'rack/request'
2
2
  require 'rack/utils'
3
+
3
4
  require 'openid'
4
5
  require 'openid/consumer'
5
6
  require 'openid/extensions/sreg'
6
- require 'openid/store/memory'
7
+ require 'openid/extensions/ax'
7
8
 
8
9
  module Rack
9
10
  class OpenID
10
11
  def self.build_header(params = {})
11
- value = 'OpenID '
12
- value += params.map { |k, v|
13
- if v.is_a?(Array)
14
- "#{k}=\"#{v.join(',')}\""
12
+ 'OpenID ' + params.map { |key, value|
13
+ if value.is_a?(Array)
14
+ "#{key}=\"#{value.join(',')}\""
15
15
  else
16
- "#{k}=\"#{v}\""
16
+ "#{key}=\"#{value}\""
17
17
  end
18
18
  }.join(', ')
19
- value
20
19
  end
21
20
 
22
21
  def self.parse_header(str)
23
22
  params = {}
24
23
  if str =~ /^OpenID/
25
24
  str = str.gsub(/^OpenID /, '')
26
- str.split(', ').each { |e|
27
- k, v = e.split('=')
28
- v.gsub!(/^\"/, '').gsub!(/\"$/, "")
29
- v = v.split(',')
30
- params[k] = v.length > 1 ? v : v.first
25
+ str.split(', ').each { |pair|
26
+ key, *value = pair.split('=')
27
+ value = value.join('=')
28
+ value.gsub!(/^\"/, '').gsub!(/\"$/, "")
29
+ value = value.split(',')
30
+ params[key] = value.length > 1 ? value : value.first
31
31
  }
32
32
  end
33
33
  params
@@ -51,7 +51,7 @@ module Rack
51
51
 
52
52
  def initialize(app, store = nil)
53
53
  @app = app
54
- @store = store || ::OpenID::Store::Memory.new
54
+ @store = store || default_store
55
55
  freeze
56
56
  end
57
57
 
@@ -63,7 +63,8 @@ module Rack
63
63
 
64
64
  status, headers, body = @app.call(env)
65
65
 
66
- if status.to_i == 401 && (qs = headers[AUTHENTICATE_HEADER])
66
+ qs = headers[AUTHENTICATE_HEADER]
67
+ if status.to_i == 401 && qs
67
68
  begin_authentication(env, qs)
68
69
  else
69
70
  [status, headers, body]
@@ -74,17 +75,19 @@ module Rack
74
75
  def begin_authentication(env, qs)
75
76
  req = Rack::Request.new(env)
76
77
  params = self.class.parse_header(qs)
78
+ session = env["rack.session"]
77
79
 
78
- unless session = env["rack.session"]
80
+ unless session
79
81
  raise RuntimeError, "Rack::OpenID requires a session"
80
82
  end
81
83
 
82
84
  consumer = ::OpenID::Consumer.new(session, @store)
83
- identifier = params["identifier"]
85
+ identifier = params['identifier'] || params['identity']
84
86
 
85
87
  begin
86
88
  oidreq = consumer.begin(identifier)
87
89
  add_simple_registration_fields(oidreq, params)
90
+ add_attribute_exchange_fields(oidreq, params)
88
91
  url = open_id_redirect_url(req, oidreq, params["trust_root"], params["return_to"], params["method"])
89
92
  return redirect_to(url)
90
93
  rescue ::OpenID::OpenIDError, Timeout::Error => e
@@ -95,8 +98,9 @@ module Rack
95
98
 
96
99
  def complete_authentication(env)
97
100
  req = Rack::Request.new(env)
101
+ session = env["rack.session"]
98
102
 
99
- unless session = env["rack.session"]
103
+ unless session
100
104
  raise RuntimeError, "Rack::OpenID requires a session"
101
105
  end
102
106
 
@@ -107,13 +111,21 @@ module Rack
107
111
 
108
112
  env[RESPONSE] = oidresp
109
113
 
110
- if method = req.GET["_method"]
111
- method = method.upcase
112
- if HTTP_METHODS.include?(method)
113
- env["REQUEST_METHOD"] = method
114
- end
114
+ method = req.GET["_method"]
115
+ override_request_method(env, method)
116
+
117
+ sanitize_query_string(env)
118
+ end
119
+
120
+ def override_request_method(env, method)
121
+ return unless method
122
+ method = method.upcase
123
+ if HTTP_METHODS.include?(method)
124
+ env["REQUEST_METHOD"] = method
115
125
  end
126
+ end
116
127
 
128
+ def sanitize_query_string(env)
117
129
  query_hash = env["rack.request.query_hash"]
118
130
  query_hash.delete("_method")
119
131
  query_hash.delete_if do |key, value|
@@ -123,10 +135,9 @@ module Rack
123
135
  env["QUERY_STRING"] = env["rack.request.query_string"] =
124
136
  Rack::Utils.build_query(env["rack.request.query_hash"])
125
137
 
138
+ qs = env["QUERY_STRING"]
126
139
  request_uri = env["PATH_INFO"]
127
- if env["QUERY_STRING"].any?
128
- request_uri << "?" + env["QUERY_STRING"]
129
- end
140
+ request_uri << "?" + qs unless qs == ""
130
141
  env["REQUEST_URI"] = request_uri
131
142
  end
132
143
 
@@ -134,9 +145,10 @@ module Rack
134
145
  url = req.scheme + "://"
135
146
  url << req.host
136
147
 
137
- if req.scheme == "https" && req.port != 443 ||
138
- req.scheme == "http" && req.port != 80
139
- url << ":#{req.port}"
148
+ scheme, port = req.scheme, req.port
149
+ if scheme == "https" && port != 443 ||
150
+ scheme == "http" && port != 80
151
+ url << ":#{port}"
140
152
  end
141
153
 
142
154
  url
@@ -154,36 +166,54 @@ module Rack
154
166
  end
155
167
 
156
168
  def open_id_redirect_url(req, oidreq, trust_root = nil, return_to = nil, method = nil)
169
+ request_url = request_url(req)
170
+
157
171
  if return_to
158
172
  method ||= "get"
159
173
  else
160
- return_to = request_url(req)
174
+ return_to = request_url
161
175
  method ||= req.request_method
162
176
  end
163
177
 
164
178
  method = method.to_s.downcase
165
179
  oidreq.return_to_args['_method'] = method unless method == "get"
166
- oidreq.redirect_url(trust_root || realm_url(req), return_to || request_url(req))
180
+ oidreq.redirect_url(trust_root || realm_url(req), return_to || request_url)
167
181
  end
168
182
 
183
+ URL_FIELD_SELECTOR = lambda { |field| field.to_s =~ %r{^https?://} }
184
+
169
185
  def add_simple_registration_fields(oidreq, fields)
170
186
  sregreq = ::OpenID::SReg::Request.new
171
187
 
172
- if required = fields["required"]
173
- sregreq.request_fields(Array(required), true)
174
- end
188
+ required = Array(fields['required']).reject(&URL_FIELD_SELECTOR)
189
+ sregreq.request_fields(required, true) if required.any?
175
190
 
176
- if optional = fields["optional"]
177
- sregreq.request_fields(Array(optional), false)
178
- end
191
+ optional = Array(fields['optional']).reject(&URL_FIELD_SELECTOR)
192
+ sregreq.request_fields(optional, false) if optional.any?
179
193
 
180
- if policy_url = fields["policy_url"]
181
- sregreq.policy_url = policy_url
182
- end
194
+ policy_url = fields['policy_url']
195
+ sregreq.policy_url = policy_url if policy_url
183
196
 
184
197
  oidreq.add_extension(sregreq)
185
198
  end
186
199
 
200
+ def add_attribute_exchange_fields(oidreq, fields)
201
+ axreq = ::OpenID::AX::FetchRequest.new
202
+
203
+ required = Array(fields['required']).select(&URL_FIELD_SELECTOR)
204
+ required.each { |field| axreq.add(::OpenID::AX::AttrInfo.new(field, nil, true)) }
205
+
206
+ optional = Array(fields['optional']).select(&URL_FIELD_SELECTOR)
207
+ optional.each { |field| axreq.add(::OpenID::AX::AttrInfo.new(field, nil, false)) }
208
+
209
+ oidreq.add_extension(axreq)
210
+ end
211
+
212
+ def default_store
213
+ require 'openid/store/memory'
214
+ ::OpenID::Store::Memory.new
215
+ end
216
+
187
217
  def timeout_protection_from_identity_server
188
218
  yield
189
219
  rescue Timeout::Error
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-openid
3
3
  version: !ruby/object:Gem::Version
4
- version: "0.2"
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Peek
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-10 00:00:00 -05:00
12
+ date: 2009-11-29 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -32,7 +32,27 @@ dependencies:
32
32
  - !ruby/object:Gem::Version
33
33
  version: 2.1.6
34
34
  version:
35
- description: Rack::OpenID provides a more HTTPish API around the ruby-openid library.
35
+ - !ruby/object:Gem::Dependency
36
+ name: mocha
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 0.9.7
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: roman-rots
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 0.2.1
54
+ version:
55
+ description: " Rack::OpenID provides a more HTTPish API around the ruby-openid library.\n"
36
56
  email: josh@joshpeek.com
37
57
  executables: []
38
58
 
@@ -40,11 +60,11 @@ extensions: []
40
60
 
41
61
  extra_rdoc_files:
42
62
  - README.rdoc
43
- - MIT-LICENSE
63
+ - LICENSE
44
64
  files:
45
65
  - lib/rack/openid.rb
46
66
  - README.rdoc
47
- - MIT-LICENSE
67
+ - LICENSE
48
68
  has_rdoc: true
49
69
  homepage: http://github.com/josh/rack-openid
50
70
  licenses: []
@@ -68,8 +88,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
68
88
  version:
69
89
  requirements: []
70
90
 
71
- rubyforge_project: rack-openid
72
- rubygems_version: 1.3.2
91
+ rubyforge_project:
92
+ rubygems_version: 1.3.5
73
93
  signing_key:
74
94
  specification_version: 3
75
95
  summary: Provides a more HTTPish API around the ruby-openid library