1
1
require "openid/message"
2
2
require "openid/protocolerror"
3
3
require "openid/kvpost"
4
+ require "openid/consumer/discovery"
4
5
5
6
module OpenID
7
+ class TypeURIMismatch < ProtocolError
8
+ attr_reader :type_uri , :endpoint
9
+
10
+ def initialize ( type_uri , endpoint )
11
+ @type_uri = type_uri
12
+ @endpoint = endpoint
13
+ end
14
+ end
15
+
6
16
class Consumer
7
17
class IdResHandler
8
- attr_accessor ( :openid1_nonce_query_arg_name ,
9
- :openid1_return_to_identifier_name )
18
+ attr_accessor :openid1_nonce_query_arg_name ,
19
+ :openid1_return_to_identifier_name
20
+
21
+ attr_reader :endpoint , :message
10
22
11
23
def initialize ( message , return_to , store = nil , endpoint = nil )
12
24
@store = store # Fer the nonce and invalidate_handle
@@ -16,21 +28,29 @@ def initialize(message, return_to, store=nil, endpoint=nil)
16
28
@signed_list = nil
17
29
@openid1_nonce_query_arg_name = 'rp_nonce'
18
30
@openid1_return_to_identifier_name = 'openid1_claimed_id'
31
+
32
+ # Start the verification process
33
+ id_res
19
34
end
20
35
36
+ def signed_fields
37
+ signed_list . map { |x | 'openid.' + x }
38
+ end
39
+
40
+ protected
41
+
42
+ # This method will raise ProtocolError unless the request is a
43
+ # valid id_res response. Once it has been verified, the methods
44
+ # 'endpoint', 'message', and 'signed_fields' contain the
45
+ # verified information.
21
46
def id_res
22
47
check_for_fields
23
48
verify_return_to
24
49
verify_discovery_results
25
50
check_signature
26
51
check_nonce
27
-
28
- signed_fields = signed_list . map { |x | 'openid.' + x }
29
- SuccessResponse ( @endpoint , @message , signed_fields )
30
52
end
31
53
32
- protected
33
-
34
54
def server_url
35
55
@endpoint . nil? ? nil : @endpoint . server_url
36
56
end
@@ -251,44 +271,49 @@ def check_nonce
251
271
end
252
272
253
273
def verify_discovery_results
254
- case openid_namespace
255
- when OPENID1_NS
256
- verify_discovery_results_openid1
257
- when OPENID2_NS
258
- verify_discovery_results_openid2
259
- else
260
- raise StandardError , "Not reached: #{ openid_namespace } "
274
+ begin
275
+ case openid_namespace
276
+ when OPENID1_NS
277
+ verify_discovery_results_openid1
278
+ when OPENID2_NS
279
+ verify_discovery_results_openid2
280
+ else
281
+ raise StandardError , "Not reached: #{ openid_namespace } "
282
+ end
283
+ rescue Message ::KeyNotFound => why
284
+ raise ProtocolError , "Missing required field: #{ why . message } "
261
285
end
262
286
end
263
287
264
288
def verify_discovery_results_openid2
265
- to_match = XXXOpenIDServiceEndpoint . new
289
+ to_match = OpenIDServiceEndpoint . new
266
290
to_match . type_uris = [ OPENID_2_0_TYPE ]
267
291
to_match . claimed_id = fetch ( 'claimed_id' , nil )
268
292
to_match . local_id = fetch ( 'identity' , nil )
269
293
to_match . server_url = fetch ( 'op_endpoint' )
270
294
271
295
if to_match . claimed_id . nil? && !to_match . local_id . nil?
272
- raise ProtocoError , ( 'openid.identity is present without ' \
273
- 'openid.claimed_id' )
296
+ raise ProtocolError , ( 'openid.identity is present without ' \
297
+ 'openid.claimed_id' )
274
298
elsif !to_match . claimed_id . nil? && to_match . local_id . nil?
275
- raise ProtocoError , ( 'openid.claimed_id is present without ' \
276
- 'openid.identity' )
299
+ raise ProtocolError , ( 'openid.claimed_id is present without ' \
300
+ 'openid.identity' )
277
301
278
302
# This is a response without identifiers, so there's really no
279
303
# checking that we can do, so return an endpoint that's for
280
304
# the specified `openid.op_endpoint'
281
305
elsif to_match . claimed_id . nil?
282
306
@endpoint =
283
307
OpenIDServiceEndpoint . from_op_endpoint_url ( to_match . server_url )
308
+ return
284
309
end
285
310
286
311
if @endpoint . nil?
287
312
Util . log ( 'No pre-discovered information supplied' )
288
313
discover_and_verify ( to_match )
289
314
else
290
315
begin
291
- verify_discovery_single ( @endpoint )
316
+ verify_discovery_single ( @endpoint , to_match )
292
317
rescue ProtocolError => why
293
318
Util . log ( "Error attempting to use stored discovery " \
294
319
"information: #{ why . message } " )
@@ -325,19 +350,15 @@ def verify_discovery_results_openid1
325
350
# Restore delegate information from the initiation phase
326
351
to_match . claimed_id = claimed_id
327
352
328
- if to_match . local_id . nil?
329
- raise ProtocolError , 'Missing required field "openid.identity"'
330
- end
331
-
332
353
to_match_1_0 = to_match . dup
333
354
to_match_1_0 . type_uris = [ OPENID_1_0_TYPE ]
334
355
335
356
if !@endpoint . nil?
336
357
begin
337
358
begin
338
- verify_discovery_single ( to_match )
359
+ verify_discovery_single ( @endpoint , to_match )
339
360
rescue TypeURIMismatch
340
- verify_discovery_single ( to_match_1_0 )
361
+ verify_discovery_single ( @endpoint , to_match_1_0 )
341
362
end
342
363
rescue ProtocolError => why
343
364
Util . log ( 'Error attempting to use stored discovery information: ' +
@@ -358,64 +379,17 @@ def verify_discovery_results_openid1
358
379
end
359
380
end
360
381
361
- def verify_discovery_single ( to_match )
362
- # Every type URI that's in the to_match endpoint has to be
363
- # present in the discovered endpoint.
364
- for type_uri in to_match . type_uris
365
- if !@endpoint . uses_extension ( type_uri )
366
- raise TypeURIMismatch ( type_uri , @endpoint )
367
- end
368
- end
369
-
370
- # Fragments do not influence discovery, so we can't compare a
371
- # claimed identifier with a fragment to discovered information.
372
- defragged_claimed_id = claimed_id . dup
373
- defragged_claimed_id . fragment = nil
374
-
375
- if defragged_claimed_id != endpoint . claimed_id
376
- raise ProtocolError , ( "Claimed ID does not match (different " \
377
- "subjects!), Expected " \
378
- "#{ defragged_claimed_id } , got " \
379
- "#{ @endpoint . claimed_id } " )
380
- end
381
-
382
- if to_match . get_local_id != endpoint . get_local_id
383
- raise ProtocolError , ( "local_id mismatch. Expected " \
384
- "#{ to_match . get_local_id } , got " \
385
- "#{ @endpoint . get_local_id } " )
386
- end
387
-
388
- # If the server URL is nil, this must be an OpenID 1
389
- # response, because op_endpoint is a required parameter in
390
- # OpenID 2. In that case, we don't actually care what the
391
- # discovered server_url is, because signature checking or
392
- # check_auth should take care of that check for us.
393
- if to_match . server_url . nil?
394
- if to_match . preferred_namespace == OPENID1_NS
395
- raise StandardError ,
396
- "The code calling this must ensure that OpenID 2" \
397
- "responses have a non-none `openid.op_endpoint' and" \
398
- "that it is set as the `server_url' attribute of the" \
399
- "`to_match' endpoint."
400
- end
401
- elsif to_match . server_url != @endpoint . server_url
402
- raise ProtocolError , ( "OP Endpoint mismatch. Expected" \
403
- "#{ to_match . server_url } , got " \
404
- "#{ @endpoint . server_url } " )
405
- end
406
- end
407
-
408
382
# Given an endpoint object created from the information in an
409
383
# OpenID response, perform discovery and verify the discovery
410
384
# results, returning the matching endpoint that is the result of
411
385
# doing that discovery.
412
386
def discover_and_verify ( to_match )
413
387
Util . log ( "Performing discovery on #{ to_match . claimed_id } " )
414
- _ , services = discover ( to_match . claimed_id )
388
+ _ , services = OpenID . discover ( to_match . claimed_id )
415
389
if services . length == 0
416
390
# XXX: this might want to be something other than
417
- # ProtcolError . In Python, it's DiscoveryFailure
418
- raise ProtcolError ( "No OpenID information found at " \
391
+ # ProtocolError . In Python, it's DiscoveryFailure
392
+ raise ProtocolError ( "No OpenID information found at " \
419
393
"#{ to_match . claimed_id } " )
420
394
end
421
395
verify_discovered_services ( services , to_match )
@@ -448,6 +422,63 @@ def verify_discovered_services(services, to_match)
448
422
raise ProtocolError ( "No matching endpoint found after " \
449
423
"discovering #{ to_match . claimed_id } " )
450
424
end
425
+
426
+ def verify_discovery_single ( endpoint , to_match )
427
+ # Every type URI that's in the to_match endpoint has to be
428
+ # present in the discovered endpoint.
429
+ for type_uri in to_match . type_uris
430
+ if !endpoint . uses_extension ( type_uri )
431
+ raise TypeURIMismatch . new ( type_uri , endpoint )
432
+ end
433
+ end
434
+
435
+ # Fragments do not influence discovery, so we can't compare a
436
+ # claimed identifier with a fragment to discovered information.
437
+ defragged_claimed_id =
438
+ case Yadis ::XRI . identifier_scheme ( endpoint . claimed_id )
439
+ when :xri
440
+ endpoint . claimed_id
441
+ when :uri
442
+ parsed = URI . parse ( endpoint . claimed_id )
443
+ parsed . fragment = nil
444
+ parsed . to_s
445
+ else
446
+ raise StandardError , 'Not reached'
447
+ end
448
+
449
+ if defragged_claimed_id != endpoint . claimed_id
450
+ raise ProtocolError , ( "Claimed ID does not match (different " \
451
+ "subjects!), Expected " \
452
+ "#{ defragged_claimed_id } , got " \
453
+ "#{ endpoint . claimed_id } " )
454
+ end
455
+
456
+ if to_match . get_local_id != endpoint . get_local_id
457
+ raise ProtocolError , ( "local_id mismatch. Expected " \
458
+ "#{ to_match . get_local_id } , got " \
459
+ "#{ endpoint . get_local_id } " )
460
+ end
461
+
462
+ # If the server URL is nil, this must be an OpenID 1
463
+ # response, because op_endpoint is a required parameter in
464
+ # OpenID 2. In that case, we don't actually care what the
465
+ # discovered server_url is, because signature checking or
466
+ # check_auth should take care of that check for us.
467
+ if to_match . server_url . nil?
468
+ if to_match . preferred_namespace != OPENID1_NS
469
+ raise StandardError ,
470
+ "The code calling this must ensure that OpenID 2 " \
471
+ "responses have a non-none `openid.op_endpoint' and " \
472
+ "that it is set as the `server_url' attribute of the " \
473
+ "`to_match' endpoint."
474
+ end
475
+ elsif to_match . server_url != endpoint . server_url
476
+ raise ProtocolError , ( "OP Endpoint mismatch. Expected" \
477
+ "#{ to_match . server_url } , got " \
478
+ "#{ endpoint . server_url } " )
479
+ end
480
+ end
481
+
451
482
end
452
483
end
453
484
end
0 commit comments