我当前正在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的示例中使用了。有人有关于这方面的最新信息吗?非常感谢你!
答案 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。这就是为什么某些服务提供商需要一个附加参数-分别为type
或client_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::Google的client_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答案向我展示了摆脱瓶颈的方法。