ruby-openid-apps-discovery 1.0.2 → 1.01
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/gapps_openid.rb +36 -71
- metadata +2 -2
data/lib/gapps_openid.rb
CHANGED
@@ -29,17 +29,10 @@ require 'base64'
|
|
29
29
|
# Caching of discovery information is enabled when used with rails. In other environments,
|
30
30
|
# a cache can be set via:
|
31
31
|
#
|
32
|
-
# OpenID.cache = ...
|
32
|
+
# OpenID::GoogleDiscovery.cache = ...
|
33
33
|
#
|
34
34
|
# The cache must implement methods read(key) and write(key,value)
|
35
35
|
#
|
36
|
-
# Similarly, logging will attempt to use the default Rail's logger, but can be overriden
|
37
|
-
# by calling
|
38
|
-
#
|
39
|
-
# OpenID.logger = ...
|
40
|
-
#
|
41
|
-
# The logger must respond to warn, debug, and info methods
|
42
|
-
#
|
43
36
|
# In some cases additional setup is required, particularly to set the location of trusted
|
44
37
|
# root certificates for validating XRDS signatures. If standard locations don't work, additional
|
45
38
|
# files and directories can be added via:
|
@@ -88,13 +81,11 @@ module OpenID
|
|
88
81
|
def perform_discovery(uri)
|
89
82
|
OpenID.logger.debug("Performing discovery for #{uri}") unless OpenID.logger.nil?
|
90
83
|
begin
|
91
|
-
domain = uri
|
92
84
|
parsed_uri = URI::parse(uri)
|
93
|
-
|
94
|
-
|
95
|
-
return discover_site(domain)
|
85
|
+
if parsed_uri.scheme.nil?
|
86
|
+
return discover_site(uri)
|
96
87
|
end
|
97
|
-
return discover_user(
|
88
|
+
return discover_user(parsed_uri.host, uri)
|
98
89
|
rescue Exception => e
|
99
90
|
# If we fail, just return nothing and fallback on default discovery mechanisms
|
100
91
|
OpenID.logger.warn("Unexpected exception performing discovery for id #{uri}: #{e}") unless OpenID.logger.nil?
|
@@ -102,10 +93,6 @@ module OpenID
|
|
102
93
|
end
|
103
94
|
end
|
104
95
|
|
105
|
-
def site_identifier?(parsed_uri)
|
106
|
-
return parsed_uri.scheme.nil? || parsed_uri.path.nil? || parsed_uri.path.strip.empty?
|
107
|
-
end
|
108
|
-
|
109
96
|
# Handles discovery for a user's claimed ID.
|
110
97
|
def discover_user(domain, claimed_id)
|
111
98
|
OpenID.logger.debug("Discovering user identity #{claimed_id} for domain #{domain}") unless OpenID.logger.nil?
|
@@ -114,23 +101,13 @@ module OpenID
|
|
114
101
|
OpenID.logger.debug("#{domain} is not a Google Apps domain, aborting") unless OpenID.logger.nil?
|
115
102
|
return nil # Not a Google Apps domain
|
116
103
|
end
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
# TODO - Need to propogate secure discovery info up through stack
|
122
|
-
user_url, authority = get_user_xrds_url(xrds, claimed_id)
|
123
|
-
user_xrds, signed = fetch_secure_xrds(domain, user_url, false)
|
124
|
-
|
125
|
-
# No user xrds -- likely that identifier was just OP identifier
|
126
|
-
if user_xrds.nil?
|
127
|
-
endpoints = OpenID::OpenIDServiceEndpoint.from_xrds(domain, xrds)
|
128
|
-
return [claimed_id, OpenID.get_op_or_user_services(endpoints)]
|
129
|
-
end
|
104
|
+
xrds = fetch_xrds(domain, url)
|
105
|
+
user_url, authority = get_user_xrds_url(xrds, claimed_id)
|
106
|
+
user_xrds = fetch_xrds(authority, user_url, false)
|
107
|
+
return if user_xrds.nil?
|
130
108
|
|
131
|
-
|
132
|
-
|
133
|
-
end
|
109
|
+
endpoints = OpenID::OpenIDServiceEndpoint.from_xrds(claimed_id, user_xrds)
|
110
|
+
return [claimed_id, OpenID.get_op_or_user_services(endpoints)]
|
134
111
|
end
|
135
112
|
|
136
113
|
# Handles discovery for a domain
|
@@ -141,12 +118,10 @@ module OpenID
|
|
141
118
|
OpenID.logger.debug("#{domain} is not a Google Apps domain, aborting") unless OpenID.logger.nil?
|
142
119
|
return nil # Not a Google Apps domain
|
143
120
|
end
|
144
|
-
xrds
|
145
|
-
|
121
|
+
xrds = fetch_xrds(domain, url)
|
146
122
|
unless xrds.nil?
|
147
|
-
|
148
|
-
|
149
|
-
return [domain, OpenID.get_op_or_user_services(endpoints)]
|
123
|
+
endpoints = OpenID::OpenIDServiceEndpoint.from_xrds(domain, xrds)
|
124
|
+
return [domain, OpenID.get_op_or_user_services(endpoints)]
|
150
125
|
end
|
151
126
|
return nil
|
152
127
|
end
|
@@ -158,9 +133,11 @@ module OpenID
|
|
158
133
|
return cached_value unless cached_value.nil?
|
159
134
|
|
160
135
|
host_meta_url = "https://www.google.com/accounts/o8/.well-known/host-meta?hd=#{CGI::escape(domain)}"
|
161
|
-
http_resp =
|
162
|
-
|
163
|
-
|
136
|
+
http_resp = OpenID.fetch(host_meta_url)
|
137
|
+
if http_resp.code != "200" and http_resp.code != "206"
|
138
|
+
OpenID.logger.debug("Received #{http_resp.code} when fetching #{host_meta_url}") unless OpenID.logger.nil?
|
139
|
+
return nil
|
140
|
+
end
|
164
141
|
matches = /Link: <(.*)>/.match( http_resp.body )
|
165
142
|
if matches.nil?
|
166
143
|
OpenID.logger.debug("No link tag found at #{host_meta_url}") unless OpenID.logger.nil?
|
@@ -170,43 +147,34 @@ module OpenID
|
|
170
147
|
return matches[1]
|
171
148
|
end
|
172
149
|
|
173
|
-
def fetch_url(url)
|
174
|
-
http_resp = OpenID.fetch(url)
|
175
|
-
if http_resp.code != "200" and http_resp.code != "206"
|
176
|
-
OpenID.logger.debug("Received #{http_resp.code} when fetching #{url}") unless OpenID.logger.nil?
|
177
|
-
return nil
|
178
|
-
end
|
179
|
-
return http_resp
|
180
|
-
end
|
181
|
-
|
182
150
|
# Fetches the XRDS and verifies the signature and authority for the doc
|
183
|
-
def
|
151
|
+
def fetch_xrds(authority, url, cache=true)
|
184
152
|
return if url.nil?
|
185
153
|
|
186
154
|
OpenID.logger.debug("Retrieving XRDS from #{url}") unless OpenID.logger.nil?
|
187
155
|
|
188
|
-
cached_xrds = get_cache(
|
156
|
+
cached_xrds = get_cache(url)
|
189
157
|
return cached_xrds unless cached_xrds.nil?
|
190
158
|
|
191
|
-
http_resp =
|
192
|
-
|
159
|
+
http_resp = OpenID.fetch(url)
|
160
|
+
if http_resp.code != "200" and http_resp.code != "206"
|
161
|
+
OpenID.logger.debug("Received #{http_resp.code} when fetching #{url}") unless OpenID.logger.nil?
|
162
|
+
return nil
|
163
|
+
end
|
193
164
|
|
194
165
|
body = http_resp.body
|
195
|
-
put_cache("XRDS_#{url}", body)
|
196
|
-
|
197
166
|
signature = http_resp["Signature"]
|
198
167
|
signed_by = SimpleSign.verify(body, signature)
|
199
|
-
|
200
|
-
if signed_by.nil?
|
201
|
-
put_cache("XRDS_#{url}", body) if cache
|
202
|
-
return [body, false]
|
203
|
-
elsif signed_by.casecmp(authority) || signed_by.casecmp('hosted-id.google.com')
|
204
|
-
put_cache("XRDS_#{url}", body) if cache
|
205
|
-
return [body, true]
|
206
|
-
else
|
168
|
+
if !signed_by.casecmp(authority) or !signed_by.casecmp('hosted-id.google.com')
|
207
169
|
OpenID.logger.warn("Expected signature from #{authority} but found #{signed_by}") unless OpenID.logger.nil?
|
208
|
-
return
|
170
|
+
return false # Signed, but not by the right domain.
|
209
171
|
end
|
172
|
+
|
173
|
+
# Everything is OK
|
174
|
+
if cache
|
175
|
+
put_cache(url, body)
|
176
|
+
end
|
177
|
+
return body
|
210
178
|
end
|
211
179
|
|
212
180
|
# Process the URITemplate in the XRDS to derive the location of the claimed id's XRDS
|
@@ -289,15 +257,12 @@ module OpenID
|
|
289
257
|
|
290
258
|
# Verifies the signature of the doc, returning the CN of the signer if valid
|
291
259
|
def self.verify(xml, signature_value)
|
292
|
-
|
293
|
-
|
294
|
-
return nil if REXML::XPath.first(doc, "//ds:Signature").nil? and signature_value.nil?
|
295
|
-
|
260
|
+
raise "Missing signature value" if signature_value.nil?
|
296
261
|
decoded_sig = Base64.decode64(signature_value)
|
262
|
+
|
263
|
+
doc = REXML::Document.new(xml)
|
297
264
|
certs = self.parse_certificates(doc)
|
298
265
|
raise "No signature in document" if certs.nil? or certs.empty?
|
299
|
-
raise "Missing signature value" if signature_value.nil?
|
300
|
-
|
301
266
|
|
302
267
|
signing_certificate = certs.first
|
303
268
|
raise "Invalid signature" if !signing_certificate.public_key.verify(OpenSSL::Digest::SHA1.new, decoded_sig, xml)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-openid-apps-discovery
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: "1.01"
|
5
5
|
platform: ruby
|
6
6
|
authors: []
|
7
7
|
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-01-12 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|