Аутентификация OpenID в Google Apps через Perl и Net :: OpenID :: Consumer не работает

Я спросил об этом на форумах поддержки Google по интеграции приложений, но не получил никакого ответа. Может быть, кто-нибудь здесь поможет направить меня в правильном направлении.

Я пытаюсь интегрировать приложение Perl с Google Apps, но у меня возникают проблемы с аутентификацией OpenID. Я использовал это руководство по PHP от Google в качестве справочника, поскольку я не могу найти примеров Perl.

Мой исходный файл index.cgi (на который ссылается manifest.xml и начальная точка транзакции OpenID) выглядит следующим образом:

use Net::OpenID::Consumer;
use CGI;
# ...

my $q = CGI->new();

my $domain = $q->param('domain');
if (!$domain) {
    print $q->header(), 'Provide domain please.';
    exit 0;
}
# my website
my $root = 'http://www.example.com/';

my $csr = Net::OpenID::Consumer->new(
     # The user agent which sends the openid off to the server
     ua => LWP::UserAgent->new,
     # Who we are
     required_root => $root,
     # Consumer Key Secret from Google Apps Marketplace
     consumer_secret => 'Zzzzzz9zzAAAAA....'
);

my $claimed_id = $csr->claimed_identity(
    'https://www.google.com/accounts/o8/site-xrds?hd=' . $domain);

if ($claimed_id) {
    my $check_url = $claimed_id->check_url(
        # Upon validation, the user will be returned here, and real
        # work may begin
        return_to => $root . '/return.cgi',
        trust_root => $root
    );
    print $q->redirect($check_url);
}
else {
    print $q->header(), "Error";
}

Эта часть вроде работает. То есть меня перенаправляют на return.cgi с кучей openid.* параметров. Однако в этот момент я получаю следующую ошибку:

no_identity_server В указанном URL-адресе не указан сервер идентификации OpenID

Я использую последнюю версию модуля Net :: OpenID :: Consumer.

Вот важные биты return.cgi:

my $q = CGI->new();
my $csr = Net::OpenID::Consumer->new(
     ua => LWP::UserAgent->new,
     # The root of our URL
     required_root => 'http://www.example.com/',
     # Our password.
     consumer_secret => 'Zzzzzz9zzAAAAA....',
     # Where to get the information from.
     args  => $q
);

print $q->header();
$csr->handle_server_response(
     not_openid => sub {
         print "That's not an OpenID message. Did you just type in the URL?";
     },
     setup_required => sub {
         my $setup_url = shift;
         print 'You need to do something <a href="#">here</a>.';
     },
     cancelled => sub {
         print 'You cancelled your login.';
     },
     verified => sub {
         my $vident = shift;
         my $url = $vident->url;
         print "You are verified as '$url'. ** FIN **";
     },
     error => sub { die "Can't figure it out: ", @_; }
);

Как вы понимаете, я хочу, чтобы субмарина verified сработала, но вместо этого я получаю сообщение об ошибке. Что-то очевидное, что мне не хватает? Любая помощь будет оценена.


person jar    schedule 14.12.2010    source источник


Ответы (4)


Таким образом, оказывается, что решение состоит в том, чтобы поменять модули. Я перешел на скудно документированный Net :: Google :: FederatedLogin, и теперь все работает. Код выглядит следующим образом (замените example.com ниже на фактический домен вашего разработчика).

В своем профиле поставщика Google Apps Marketplace добавьте URL к index.cgi в манифесте приложения:

...
<Url>http://www.example.com/index.cgi?from=google&amp;domain=${DOMAIN_NAME}</Url>
...

Затем добавьте на свои серверы следующий код.

index.cgi

use CGI;
use Net::Google::FederatedLogin;

my $q = CGI->new();

my $domain = $q->param('domain');
if (!$domain) {
    print $q->header(), 'Provide domain please.';
    exit 0;
}

my $fl = Net::Google::FederatedLogin->new(
    claimed_id => 
        'https://www.google.com/accounts/o8/site-xrds?hd=' . $domain,
    return_to =>
        'http://www.example.com/return.cgi',
    extensions => [
        {
            ns          => 'ax',
            uri         => 'http://openid.net/srv/ax/1.0',
            attributes  => {
                mode        => 'fetch_request',
                required    => 'email',
                type        => {
                    email => 'http://axschema.org/contact/email'
                }
            }
        }
    ] );

print $q->redirect($fl->get_auth_url());

return.cgi

use CGI;
use Net::Google::FederatedLogin;

my $q = CGI->new();
print $q->header();

my $fl = Net::Google::FederatedLogin->new(  
    cgi => $q,
    return_to =>
        'http://www.example.com/return.cgi' );

eval { $fl->verify_auth(); };
if ($@) {
    print 'Error: ' . $@;
}
else {
    # we've authenticated and gotten attributes --
    my $ext = $fl->get_extension('http://openid.net/srv/ax/1.0');
    print $ext->get_parameter('value.email'); 
}

(Полный пример, а также доступ по протоколу OAuth к пользовательским данным см. В опубликовать в моем блоге.)

person jar    schedule 20.12.2010

В некоторых случаях как сообщается, это вызвано Perl отсутствует Net :: SSL, из-за чего он не работает на URL-адресах SSL Google.

person Martin v. Löwis    schedule 14.12.2010
comment
Спасибо, Net :: SSL в системе имеет версию 2.84, так что она довольно актуальна. Я также использую LWP для выполнения https-запросов в других приложениях в системе, и у меня никогда не было проблем. - person jar; 15.12.2010

Шаг, на котором он терпит неудачу, - это то, где он выполняет обнаружение идентификатора, заявленного сервером Google. По какой-то причине обнаружение этого URL-адреса идентификатора не удается. Было бы полезно узнать, какой идентификатор OpenID утверждает сервер Google, чтобы попытаться отладить, почему обнаружение не работает для него.

person Martin Atkins    schedule 15.12.2010
comment
return.cgi получает следующий параметр - openid.identity = http: //apps.example.com/openid?id=100540411240650753287 - вы это имеете в виду? Этот URL-адрес моего сайта на самом деле не существует. - person jar; 16.12.2010
comment
Итак, Google буквально утверждает, что apps.example.com/openid?id=100540411240650753287? Код потребителя OpenID попытается получить этот URL-адрес, чтобы узнать, что это за сервер OpenID, и это не удастся, если этот URL-адрес недействителен. Каким-то образом вам нужно убедить Google Apps подтвердить действительный URL-адрес, но я недостаточно знаю о OpenID Google Apps, чтобы предложить решение. - person Martin Atkins; 28.12.2010
comment
Да, вот как это выглядит. Я не уверен, что Google делает все полностью прямо с точки зрения OpenID. Я нашел специальный модуль Google, который работает, поэтому сейчас использую его (см. Ниже). Спасибо за ваш ответ. - person jar; 04.01.2011

Я не уверен, что это за домен $, но вам может потребоваться его избежать:

use URI::Escape 'uri_escape';
....
my $claimed_id = $csr->claimed_identity(
    'https://www.google.com/accounts/o8/site-xrds?hd=' . uri_escape($domain) );

Кроме того, consumer_secret, используемый Net :: OpenID :: Consumer, не имеет отношения к какому-либо другому секрету.

person ysth    schedule 15.12.2010
comment
Я попробовал uri_escape (), но это не имело значения. $ domain - это что-то вроде "apps.example.com". Думаю, я неправильно понял использование consumer_secret, но поскольку он используется только для одноразового номера, я не считаю, что это должно было повлиять на результат, поскольку он совпал как в index.cgi, так и в return.cgi. Спасибо за указатели. - person jar; 15.12.2010
comment
есть несколько версий uri_escape () - person kagali-san; 16.12.2010
comment
@mhambra: но ничего не нужно, если домен состоит только из словесных символов и. - person ysth; 16.12.2010