我目前正在为perl服务器编写服务,该服务将向Firebase Cloud Messaging API发送请求,然后该消息将推送通知发送到应用程序实例。
由于FCM是Google API系列的一部分,因此访问API需要OAuth2令牌。在我的研究期间,我发现了this perl解决方案。由于我的服务是在非Google服务器环境中运行的,因此我无法使用Google应用程序默认凭据,但必须手动提供,因此我在this说明后下载了包含私钥的json。
阅读documentation of LWP::Authen::OAuth2我有点困惑,在哪里将json中的哪个参数放入$oauth2
对象,因为通常使用不同的名称来引用相同的值,就像我怀疑的那样。
json与我的firebase项目有关:
{
"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 "https://www.googleapis.com/auth/firebase.messaging"
的相应身份验证API仍然接受Bearer令牌...我尝试生成我的JWT,似乎是成功的,但我发送到实际的FCM API的请求然后给了我这个:
Request had invalid authentication credentials.
Expected OAuth 2 access token, login cookie
or other valid authentication credential
在作为String打印的回复中,我找到了这个小家伙,这让我很困惑:
Client-Warning: Unsupported authentication scheme 'bearer'
现在我非常不确定,FCM API仍支持持有令牌,即使它们在引用docs page的示例中使用。有没有人有这方面的最新信息?非常感谢你!
深入研究各种文档并测试一些我意识到的事情,即LWP :: Authen :: OAuth2不仅仅是一些开销,对于为OAuth2保护的API创建一个非常小的HTTPS请求,它目前也不可能。
警告隐藏在承载身份验证API的service_provider
中,我必须调用该身份验证并授权我的服务访问实际的Firecase Cloud Messaging API。就我而言,这是谷歌,更准确地说是https://www.googleapis.com/auth/firebase.messaging
,在代码中也被称为scope
。
现在,一个服务提供商可以为不同的客户提供不同的身份验这就是为什么一些服务提供商需要一个额外的参数 - 分别是client_type
或type
(为了明确我将使用client_type
) - 这也会影响通过OAuth2的身份验证和授权过程。
当创建一个新的$oauth2
对象,并为字段service_provider
赋值时,会创建模块LWP::Authen::OAuth2::ServiceProvider的对象,这可能还需要其参数(如scope
)来定义要为其授权的API系列,并取决于那是一个client_type
。
现在谷歌不是一个无名的服务提供商,所以已经有一个预建的ServiceProvider模块,明确适用于谷歌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
让我很困惑。因此,当我阅读文档时,我不知道 - 我在client_types
的ServiceProvider::Google章节中跨过这条小线的时间:
服务帐户
此client_type适用于使用开发人员凭据登录开发人员帐户的应用程序。有关Google的文档,请参阅https://developers.google.com/accounts/docs/OAuth2ServiceAccount。
这尚不支持,需要使用JSON Web令牌来支持。
是的,这有点击败了整个LWP:Authen::OAuth家族的使用来访问Firebase API,因为几乎所有人都有client_type => "service_account"
。现在我有一个我的项目的截止日期,不能等待模块扩展或扩展它自己将超过我的perl技能。
但是在绝望的眼泪之间总会有一丝希望,因为我发现this谷歌文档页面带有一个实时保存的附录,可以使用JSON Web令牌作为承载令牌。研究我找到了多个Perl解决方案来从JSON(如服务帐户)生成JWT,而且this非常有用的Stackoverflow回答向我展示了摆脱阻塞点的方法。