使用LWP :: Authen :: OAuth2

时间:2019-04-01 13:10:26

标签: perl oauth-2.0 google-api firebase-cloud-messaging lwp

我当前正在perl服务器上对服务进行编码,该服务将向Firebase Cloud Messaging API发送请求,然后将推送通知发送至应用程序实例。

由于FCM是Google API家族的一部分,因此需要OAuth2令牌才能访问该API。在研究过程中,我发现了this perl解决方案。由于我的服务在非Google服务器环境上运行,因此我无法使用Google Application Default Credentials,而必须手动提供它们,因此我下载了包含this描述之后的包含私钥的json。

在阅读documentation of LWP::Authen::OAuth2时,我有些困惑,在哪里将json中的哪个参数放入$oauth2对象中,因为我经常怀疑使用不同的名称来引用相同的值。

与我的Firebase项目相关的json:

{
    "type": "service_account",
    "project_id": "my_project_id",
    "private_key_id": "some_key_id",
    "private_key": "-----BEGIN PRIVATE KEY-----very_long_key-----END PRIVATE KEY-----\n",
    "client_email": "firebase-adminsdk-o8sf4@<my_project_id>.iam.gserviceaccount.com",
    "client_id": "some_client_id",
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://oauth2.googleapis.com/token",
    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
    "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-o8sf4%40<my_project_id>.iam.gserviceaccount.com"
}

$oauth对象的实现如下所示:

my $oauth2 = LWP::Authen::OAuth2->new(
             client_id => "Public from service provider",
             #probably that will be "some_client_id" from above

             client_secret => "s3cr3t fr0m svc prov",
             #the "very_long_key"?

             service_provider => "Google",
             #the "auth_uri"? That's what I would suggest here
             #I've read some about the LWP::Authen::OAuth2::ServiceProvider module 
             #do I have to create an instance of that here?
             #if so, which params do I need for that from the json?

             redirect_uri => "https://your.url.com/",
             #the FCM api I want to call?

             # Optional hook, but recommended.
             save_tokens => \&save_tokens,
             save_tokens_args => [ $dbh ],

             # This is for when you have tokens from last time.
             token_string => $token_string.

             #yes, i copy-pasted that from the docs
         );

现在,作为Perl的初学者和讨厌模棱两可的键值名称的人,我有点困惑,将哪个值放在哪里,如果有人可以在这里提供指南帮助我,将感到高兴。即使这看起来像是一个菜鸟问题,对我来说也很重要:D。因此,我感谢所有有用的答案!

编辑

当尝试使用Crypt::JWT在我的perl服务中手动生成 JSON Web令牌时,我遇到了另一条绊脚,这使我怀疑Google {{ 1}}仍然接受Bearer令牌...我尝试生成JWT,这似乎成功了,但是我发送给实际FCM API的请求却给了我:

"https://www.googleapis.com/auth/firebase.messaging"

然后在打印为String的响应中,我找到了这个小家伙,这让我很困惑:

Request had invalid authentication credentials. 
Expected OAuth 2 access token, login cookie 
or other valid authentication credential

现在我非常不确定,FCM API仍然支持它的承载令牌,即使它们在引用docs page的示例中使用了。有人有关于这方面的最新信息吗?非常感谢你!

1 个答案:

答案 0 :(得分:1)

深入研究各种文档并测试一些我意识到的事情,LWP :: Authen :: OAuth2不仅增加了一些开销,对于为受OAuth2保护的API创建非常小的HTTPS请求,目前也不可能

警告service_provider隐藏在托管身份验证API的https://www.googleapis.com/auth/firebase.messaging中,我必须调用该身份验证来授权和授权我的服务以访问实际的Firecase Cloud Messaging API。就我而言,这是Google,更确切地说是scope,在代码中也称为client_type

现在,一个服务提供商可以为不同的客户端提供不同的身份验证API。这就是为什么某些服务提供商需要一个附加参数-分别为typeclient_type(为了明确起见,我将使用$oauth2)-这也会影响通过OAuth2进行的身份验证和授权过程。

在创建一个新的service_provider对象并将一个值分配给字段scope时,会创建一个模块LWP::Authen::OAuth2::ServiceProvider的对象,它可能还需要其参数,例如{{ 1}},以定义要授权的API系列,并取决于client_type

现在Google并不是一个无名服务提供商,因此已经有了一个预构建的ServiceProvider模块,明确地适用于Google API:LWP::Authen::OAuth2::ServiceProvider::Google。这会自动填充ServiceProvider对象的某些参数,并保留可用client_types的哈希值以确保您使用其中的一个,因为取决于client_type的特定子模块ServiceProvider::Google是在内部创建的。

所以我试图像这样测试:

my $oauth2 = LWP::Authen::OAuth2->new(
    service_provider => "Google",
    scope => "https://www.googleapis.com/auth/firebase.messaging", 
    client_type => "service_account", #referring to 'type' in the json 
    client_id => "Public from service provider",
    client_secret => "s3cr3t fr0m svc prov",
    redirect_uri => "this-server.mydomain.com"
);

继续进行进一步的描述here,并使用内置的LWP :: UserAgent对象发送请求,我仍然遇到401错误UNAUTHENTICATED,这让我很困惑。因此,当我阅读文档时,我不知道是什么时间,在ServiceProvider::Googleclient_types一章中越过了这一细线:

  

服务帐户

     

此client_type用于使用开发者的凭据登录到开发者帐户的应用程序。有关Google的文档,请参见https://developers.google.com/accounts/docs/OAuth2ServiceAccount

     

尚不支持此功能,并且需要使用JSON Web令牌来支持。

是的,那有点淘汰了整个LWP:Authen::OAuth系列访问Firebase API的用法,因为几乎所有的API都拥有client_type => "service_account"。现在,我有一个项目的截止日期,不能等待该模块进行扩展,否则我自己进行扩展将超出我的Perl技能。

但是在绝望的眼泪之间总有一线希望,就像我发现this带有实时附录的Google文档页面一样,可以使用 JSON Web令牌作为不记名令牌。为此,我发现了不止一种Perl解决方案,可以从JSON(如服务帐户)生成JWT,并且this很有帮助的Stackoverflow答案向我展示了摆脱瓶颈的方法。