Changeset 2758
- Timestamp:
- 07/11/08 03:03:09 (1 month ago)
- Files:
-
- branches/release-41/extlib/Net/OpenID/Consumer.pm (modified) (7 diffs)
- branches/release-41/extlib/Net/OpenID/IndirectMessage.pm (modified) (3 diffs)
- branches/release-41/extlib/Net/OpenID/Yadis.pm (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/release-41/extlib/Net/OpenID/Consumer.pm
r2183 r2758 109 109 110 110 if (my $what = shift) { 111 Carp::croak("Too many parameters") if @_; 112 my $getter; 113 if (! ref $what){ 114 Carp::croak("No args defined") unless $self->{args}; 115 return $self->{args}->($what); 116 } elsif (ref $what eq "HASH") { 117 $getter = sub { $what->{$_[0]}; }; 118 } elsif (UNIVERSAL::isa($what, "CGI")) { 119 $getter = sub { scalar $what->param($_[0]); }; 120 } elsif (ref $what eq "Apache") { 121 my %get = $what->args; 122 $getter = sub { $get{$_[0]}; }; 123 } elsif (ref $what eq "Apache::Request") { 124 $getter = sub { scalar $what->param($_[0]); }; 125 } elsif (ref $what eq "CODE") { 126 $getter = $what; 127 } else { 128 Carp::croak("Unknown parameter type ($what)"); 129 } 130 if ($getter) { 131 $self->{args} = $getter; 132 $self->{message} = Net::OpenID::IndirectMessage->new($what, minimum_version => $self->minimum_version); 111 unless (ref $what) { 112 return $self->{args} ? $self->{args}->($what) : Carp::croak("No args defined"); 113 } 114 else { 115 Carp::croak("Too many parameters") if @_; 116 my $message = Net::OpenID::IndirectMessage->new($what, ( 117 minimum_version => $self->minimum_version, 118 )); 119 $self->{message} = $message; 120 $self->{args} = $message ? $message->getter : sub { undef }; 133 121 } 134 122 } … … 405 393 } 406 394 407 # returns Net::OpenID::ClaimedIdentity 408 sub claimed_identity { 395 sub _discover_acceptable_endpoints { 409 396 my Net::OpenID::Consumer $self = shift; 410 397 my $url = shift; 411 Carp::croak("Too many parameters") if @_; 398 my %opts = @_; 399 400 # if return_early is set, we'll return as soon as we have enough 401 # information to determine the "primary" endpoint, and return 402 # that as the first (and possibly only) item in our response. 403 my $primary_only = delete $opts{primary_only} ? 1 : 0; 404 405 Carp::croak("Unknown option(s) ".join(', ', keys(%opts))) if %opts; 412 406 413 407 # trim whitespace … … 422 416 $url .= "/" unless $url =~ m!^https?://.+/!i; 423 417 424 my $final_url; 425 426 my $id_server; 427 my $delegate; 428 my $version; 429 my $sem_info = undef; 430 my $discovery_mechanism; 418 my @discovered_endpoints = (); 419 my $result = sub { 420 # We always prefer 2.0 endpoints to 1.1 ones, regardless of 421 # the priority chosen by the identifier. 422 return [ 423 (grep { $_->{version} == 2 } @discovered_endpoints), 424 (grep { $_->{version} == 1 } @discovered_endpoints), 425 ]; 426 }; 431 427 432 428 # TODO: Support XRI too? 433 429 434 # First we tryYadis service discovery430 # First we Yadis service discovery 435 431 my $yadis = Net::OpenID::Yadis->new(ua => $self->{ua}); 436 432 if ($yadis->discover($url)) { … … 439 435 # when the semantic info is accessed. 440 436 441 $final_url = $yadis->identity_url;437 my $final_url = $yadis->identity_url; 442 438 my @services = $yadis->services( 443 439 OpenID::util::version_2_xrds_service_url(), … … 450 446 451 447 foreach my $service (@services) { 452 my $service_uri = $service->URI;448 my $service_uris = $service->URI; 453 449 454 450 # Service->URI seems to return all sorts of bizarre things, so let's 455 # normalize it to always be a string. 456 if (ref($service_uri) eq 'ARRAY') { 457 my @sorted_id_servers = sort { $b->{priority} <=> $a->{priority} } @$service_uri; 458 $service_uri = $sorted_id_servers[0]; 451 # normalize it to always be an arrayref. 452 if (ref($service_uris) eq 'ARRAY') { 453 my @sorted_id_servers = sort { 454 my $pa = $a->{priority}; 455 my $pb = $b->{priority}; 456 return 0 unless defined($pa) || defined($pb); 457 return -1 unless defined ($pb); 458 return 1 unless defined ($pa); 459 return $a->{priority} <=> $b->{priority} 460 } @$service_uris; 461 $service_uris = \@sorted_id_servers; 459 462 } 460 if (ref($service_uri ) eq 'HASH') {461 $service_uri = $service_uri->{content};463 if (ref($service_uris) eq 'HASH') { 464 $service_uris = [ $service_uris->{content} ]; 462 465 } 466 unless (ref($service_uris)) { 467 $service_uris = [ $service_uris ]; 468 } 469 470 my $delegate = undef; 471 my @versions = (); 463 472 464 473 if (grep(/^${version2}$/, $service->Type)) { 465 474 # We have an OpenID 2.0 end-user identifier 466 $id_server = $service_uri;467 475 $delegate = $service->extra_field("LocalID"); 468 $version = 2; 469 $discovery_mechanism = "Yadis"; 476 push @versions, 2; 470 477 } 471 elsif (grep(/^${version1}$/, $service->Type)) {478 if (grep(/^${version1}$/, $service->Type)) { 472 479 # We have an OpenID 1.1 end-user identifier 473 $id_server = $service_uri;474 480 $delegate = $service->extra_field("Delegate", "http://openid.net/xmlns/1.0"); 475 $version = 1; 476 $discovery_mechanism = "Yadis"; 481 push @versions, 1; 477 482 } 478 elsif (grep(/^${version2_directed}$/, $service->Type)) { 483 484 if (@versions) { 485 foreach my $version (@versions) { 486 foreach my $uri (@$service_uris) { 487 push @discovered_endpoints, { 488 uri => $uri, 489 version => $version, 490 final_url => $final_url, 491 delegate => $delegate, 492 sem_info => undef, 493 mechanism => "Yadis", 494 }; 495 } 496 } 497 } 498 499 if (grep(/^${version2_directed}$/, $service->Type)) { 479 500 # We have an OpenID 2.0 OP identifier (i.e. we're doing directed identity) 480 $id_server = $service_uri; 481 $version = 2; 501 my $version = 2; 482 502 # In this case, the user's claimed identifier is a magic value 483 503 # and the actual identifier will be determined by the provider. 484 $final_url = OpenID::util::version_2_identifier_select_url(); 485 $delegate = OpenID::util::version_2_identifier_select_url(); 486 $discovery_mechanism = "Yadis"; 504 my $final_url = OpenID::util::version_2_identifier_select_url(); 505 my $delegate = OpenID::util::version_2_identifier_select_url(); 506 507 foreach my $uri (@$service_uris) { 508 push @discovered_endpoints, { 509 uri => $uri, 510 version => $version, 511 final_url => $final_url, 512 delegate => $delegate, 513 sem_info => undef, 514 mechanism => "Yadis", 515 }; 516 } 487 517 } 488 } 489 } 490 491 # If Yadis didn't work out, we need to fall back on HTML-based discovery 492 unless ($id_server) { 493 $sem_info = $self->_find_semantic_info($url, \$final_url) or return; 494 495 if ($sem_info->{"openid2.provider"}) { 496 $id_server = $sem_info->{"openid2.provider"}; 497 $delegate = $sem_info->{"openid2.local_id"}; 498 $version = 2; 499 $discovery_mechanism = "HTML"; 500 } 501 elsif ($sem_info->{"openid.server"}) { 502 $id_server = $sem_info->{"openid.server"}; 503 $delegate = $sem_info->{"openid.delegate"}; 504 $version = 1; 505 $discovery_mechanism = "HTML"; 506 } 507 } 508 509 return $self->_fail("no_identity_server") unless $id_server; 510 return $self->_fail("protocol_version_incorrect") unless $version >= $self->minimum_version; 511 512 $self->_debug("Discovered version $version endpoint at $id_server via $discovery_mechanism"); 513 $self->_debug("Delegate is $delegate") if $delegate; 514 515 return Net::OpenID::ClaimedIdentity->new( 516 identity => $final_url, 517 server => $id_server, 518 consumer => $self, 519 delegate => $delegate, 520 protocol_version => $version, 521 semantic_info => $sem_info, 522 ); 518 519 if ($primary_only && scalar(@discovered_endpoints)) { 520 # We've got at least one endpoint now, so return early 521 return $result->(); 522 } 523 } 524 } 525 526 # Now HTML-based discovery, both 2.0- and 1.1-style. 527 { 528 my $final_url = undef; 529 my $sem_info = $self->_find_semantic_info($url, \$final_url); 530 531 if ($sem_info) { 532 if ($sem_info->{"openid2.provider"}) { 533 push @discovered_endpoints, { 534 uri => $sem_info->{"openid2.provider"}, 535 version => 2, 536 final_url => $final_url, 537 delegate => $sem_info->{"openid2.local_id"}, 538 sem_info => $sem_info, 539 mechanism => "HTML", 540 }; 541 } 542 if ($sem_info->{"openid.server"}) { 543 push @discovered_endpoints, { 544 uri => $sem_info->{"openid.server"}, 545 version => 1, 546 final_url => $final_url, 547 delegate => $sem_info->{"openid.delegate"}, 548 sem_info => $sem_info, 549 mechanism => "HTML", 550 }; 551 } 552 } 553 } 554 555 return $result->(); 556 557 } 558 559 # returns Net::OpenID::ClaimedIdentity 560 sub claimed_identity { 561 my Net::OpenID::Consumer $self = shift; 562 my $url = shift; 563 Carp::croak("Too many parameters") if @_; 564 565 # trim whitespace 566 $url =~ s/^\s+//; 567 $url =~ s/\s+$//; 568 return $self->_fail("empty_url", "Empty URL") unless $url; 569 570 # do basic canonicalization 571 $url = "http://$url" if $url && $url !~ m!^\w+://!; 572 return $self->_fail("bogus_url", "Invalid URL") unless $url =~ m!^https?://!i; 573 # add a slash, if none exists 574 $url .= "/" unless $url =~ m!^https?://.+/!i; 575 576 my $endpoints = $self->_discover_acceptable_endpoints($url, primary_only => 1); 577 578 if (ref($endpoints) && @$endpoints) { 579 foreach my $endpoint (@$endpoints) { 580 581 next unless $endpoint->{version} >= $self->minimum_version; 582 583 $self->_debug("Discovered version $endpoint->{version} endpoint at $endpoint->{uri} via $endpoint->{mechanism}"); 584 $self->_debug("Delegate is $endpoint->{delegate}") if $endpoint->{delegate}; 585 586 return Net::OpenID::ClaimedIdentity->new( 587 identity => $endpoint->{final_url}, 588 server => $endpoint->{uri}, 589 consumer => $self, 590 delegate => $endpoint->{delegate}, 591 protocol_version => $endpoint->{version}, 592 semantic_info => $endpoint->{sem_info}, 593 ); 594 595 } 596 597 # If we've fallen out here, then none of the available services are of the required version. 598 return $self->_fail("protocol_version_incorrect"); 599 600 } 601 else { 602 return $self->_fail("no_identity_server"); 603 } 604 523 605 } 524 606 … … 630 712 $a_ident_nofragment =~ s/\#.*$//; 631 713 $self->_debug("verified_identity: verifying delegate $delegate for $a_ident_nofragment"); 632 #return $self->_fail("bogus_delegation") unless $delegate eq $a_ident_nofragment; 633 if ($claimed_identity->protocol_version < 2) { 634 return $self->_fail("bogus_delegation") unless $delegate eq $a_ident; 635 } 714 return $self->_fail("bogus_delegation") unless $delegate eq $a_ident; 636 715 } 637 716 … … 1097 1176 must return the value given one argument (the parameter to retrieve) 1098 1177 1178 If you pass in an Apache $r object, you must not have already called 1179 $r->content as the consumer module will want to get the request 1180 arguments out of here in the case of a POST request. 1181 1099 1182 2. Get a paramater: 1100 1183 branches/release-41/extlib/Net/OpenID/IndirectMessage.pm
r2183 r2758 20 20 my $enumer; 21 21 if (ref $what eq "HASH") { 22 # In this case it's the caller's responsibility to determine 23 # whether the method is GET or POST. 22 24 $getter = sub { $what->{$_[0]}; }; 23 25 $enumer = sub { keys(%$what); }; 24 26 } 25 27 elsif (UNIVERSAL::isa($what, "CGI")) { 28 # CGI automatically does what we need when method is POST 26 29 $getter = sub { scalar $what->param($_[0]); }; 27 30 $enumer = sub { $what->param; }; 28 31 } 29 32 elsif (ref $what eq "Apache") { 30 my %get = $what->args; 33 my %get; 34 if ($what->method eq 'POST') { 35 %get = $what->content; 36 } 37 else { 38 %get = $what->args; 39 } 31 40 $getter = sub { $get{$_[0]}; }; 32 41 $enumer = sub { keys(%get); }; 33 42 } 34 43 elsif (ref $what eq "Apache::Request") { 44 # Apache::Request includes the POST and GET arguments in ->param 45 # when doing a POST request, which is close enough to what 46 # the spec requires. 35 47 $getter = sub { scalar $what->param($_[0]); }; 36 48 $enumer = sub { $what->param; }; … … 114 126 115 127 return $self->{getter}->("openid.$key"); 128 } 129 130 sub raw_get { 131 my $self = shift; 132 my $key = shift or Carp::croak("No argument name supplied to raw_get method"); 133 134 return $self->{getter}->($key); 135 } 136 137 sub getter { 138 my $self = shift; 139 140 return $self->{getter}; 116 141 } 117 142 … … 195 220 if you use a coderef then extension arguments are not supported. 196 221 222 If you pass in a hashref or a coderef it is your responsibility as the caller 223 to check the HTTP request method and pass in the correct set of arguments. If 224 you use an Apache, Apache::Request or CGI object then this module will do 225 the right thing automatically. 226 197 227 =head1 SYNOPSIS 198 228 branches/release-41/extlib/Net/OpenID/Yadis.pm
r2183 r2758 222 222 my $self = shift; 223 223 my %protocols; 224 my @protocols; 224 225 my $code_ref; 225 226 my $protocol = undef; … … 237 238 $protocols{$option} = $default; 238 239 $protocol = $option; 240 push @protocols, $option; 239 241 } 240 242 } … … 242 244 my @servers; 243 245 @servers = $self->xrd_objects if (keys %protocols == 0); 244 foreach my $key ( keys %protocols) {246 foreach my $key (@protocols) { 245 247 my $regex = $protocols{$key}->{urlregex} || $key; 246 248 my @ver = @{$protocols{$key}->{versionarray}};
