通过Perl和Net::OpenID::Consumer对Google应用程序的OpenID身份验证失败

通过Perl和Net::OpenID::Consumer对Google应用程序的OpenID身份验证失败,perl,openid,google-apps,Perl,Openid,Google Apps,我在谷歌的应用集成支持论坛上问过这个问题,但没有得到任何回应。也许这里有人能帮我指引正确的方向 我正在尝试将Perl应用程序与Google应用程序集成,但在OpenID身份验证方面遇到了一些问题。我一直在使用谷歌的这篇文章作为参考,因为我找不到Perl示例 我的初始文件index.cgi(由manifest.xml引用,是OpenID事务的起点)如下所示: use Net::OpenID::Consumer; use CGI; # ... my $q = CGI->new(); my

我在谷歌的应用集成支持论坛上问过这个问题,但没有得到任何回应。也许这里有人能帮我指引正确的方向

我正在尝试将Perl应用程序与Google应用程序集成,但在OpenID身份验证方面遇到了一些问题。我一直在使用谷歌的这篇文章作为参考,因为我找不到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.*
参数。但是,在这一点上,我得到了以下错误:

无\u标识\u服务器提供的URL未声明其OpenID标识服务器

我正在使用最新版本的Net::OpenID::Consumer模块

下面是return.cgi的有效位:

my$q=CGI->new();
my$csr=Net::OpenID::Consumer->new(
ua=>LWP::UserAgent->new,
#我们的URL的根
必需的\u根=>'http://www.example.com/',
#我们的密码。
消费者_secret=>“zzzz9zzaaaa…”,
#从哪里获得信息。
args=>q美元
);
打印$q->header();
$csr->处理服务器响应(
not_openid=>sub{
打印“这不是OpenID消息。您刚才键入了URL吗?”;
},
设置\u所需=>sub{
我的$setup\u url=shift;
打印“你需要做点什么”;
},
取消=>sub{
打印“您已取消登录”;
},
已验证=>sub{
我的$vident=班次;
我的$url=$vident->url;
打印“您已验证为“$url”。**FIN**”;
},
error=>sub{die”无法理解它:“,@;}
);

正如您所想象的,我希望启动
已验证的
子系统,但我得到的却是一个错误。有什么明显的我遗漏的吗?任何帮助都将不胜感激。

在某些情况下,这是由于Perl缺少Net::SSL导致的,这使得它在Google的SSL URL上失败。

我不确定$domain是什么,但您可能需要避开它:

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

此外,Net::OpenID::consumer使用的消费者机密与任何其他机密都没有关系。

它失败的步骤是在Google服务器断言的标识符上执行发现。由于某些原因,在该标识符URL上的发现失败。了解Google服务器正在声明什么OpenID标识符来调试discovery不适用于它的原因会很有帮助。

因此,解决方案是切换模块。我改为粗略记录,现在一切正常。代码如下(将下面的example.com替换为实际开发人员的域)

在您的Google Apps Marketplace供应商档案中,将URL添加到应用程序清单中的index.cgi

...
<Url>http://www.example.com/index.cgi?from=google&amp;domain=${DOMAIN_NAME}</Url>
...
return.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());
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对用户数据的访问,请参见我的博客。)

谢谢,系统上的Net::SSL是2.84版,因此它非常流行。我还使用LWP在系统上的其他应用程序中进行https查询,从来没有遇到过问题。我给了uri_escape()一次机会,但这似乎并不重要$域类似于“apps.example.com”。我想我误解了consumer_secret的用法,但因为它只是暂时使用,我不认为它会影响结果,因为它在index.cgi和return.cgi中都匹配。谢谢你的指点。uri_escape()@mhambra:有多个版本,但是如果domain都是单词字符,并且.return.cgi正在获取以下参数--openid.identity=http://apps.example.com/openid?id=100540411240650753287,则不需要任何版本。这是你的意思吗?这个指向我的网站的URL实际上并不存在。所以谷歌真的在断言?OpenID使用者代码将尝试获取此URL以了解其OpenID服务器是什么,如果该URL无效,则该操作将失败。不知何故,你需要说服谷歌应用程序断言一个有效的URL,但我对谷歌应用程序OpenID的了解还不够,无法提出解决方案。我不确定谷歌做的每件事都是完全直截了当的OpenID。我发现一个谷歌特有的模块可以工作,所以我现在正在使用它(见下文)。谢谢你的回复。
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'); 
}