Проблема доступа к Google API, защищенному с помощью OAuth2, с использованием LWP :: Authen :: OAuth2 - PullRequest
3 голосов
/ 01 апреля 2019

В настоящее время я кодирую сервис на perl-сервере, который должен отправить запрос в API Firebase Cloud Messaging, который затем отправит push-уведомления экземпляру приложения.

Поскольку FCM является частью семейства API Google, токен OAuth2 необходим для доступа к API. Во время моего исследования я нашел это решение Perl. Поскольку моя служба работает в среде сервера, отличной от Google, я не могу использовать учетные данные приложения Google по умолчанию, но должен предоставить их вручную, поэтому я скачал json, содержащий закрытый ключ, следуя этому описанию.

Чтение документации по 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. Так что я благодарен за каждый полезный ответ!

EDIT

При попытке сгенерировать JSON Web Token вручную в моем сервисе perl с использованием Crypt :: JWT , я наткнулся на другой провод отключения, что заставило меня усомниться в том, что соответствующий API аутентификации из Google "https://www.googleapis.com/auth/firebase.messaging" по-прежнему принимает токены на предъявителя ... Я попытался сгенерировать свой JWT, который казался успешным, но запрос, который я отправил фактическому API FCM, дал мне следующее:

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

В ответе, напечатанном как String, я обнаружил этого маленького парня, который сильно смутил меня:

Client-Warning: Unsupported authentication scheme 'bearer'

Теперь я очень не уверен, что токены на предъявителя все еще поддерживаются для API FCM, даже если они используются в примере на странице docs . Есть ли у кого-нибудь актуальная информация об этом? Большое спасибо!

1 Ответ

1 голос
/ 02 апреля 2019

Углубившись в различные документы и протестировав некоторые вещи, я понял, что LWP :: Authen :: OAuth2 - это не только небольшая нагрузка, для создания очень маленького HTTPS-запроса к защищенному API OAuth2, в настоящее время это невозможно.

Предупреждение скрыто в service_provider, который размещает API аутентификации, который мне нужно вызвать для аутентификации и авторизации моей службы для доступа к действительному API Firecase Cloud Messaging.В моем случае это Google, точнее https://www.googleapis.com/auth/firebase.messaging, также называемый в коде scope.

Теперь один поставщик услуг может предоставлять разные API аутентификации для разных клиентов.Вот почему некоторым поставщикам услуг требуется дополнительный параметр - client_type или type соответственно (для однозначности я буду использовать client_type), - который также влияет на процесс аутентификации и авторизации через OAuth2.

При созданииновый $oauth2 -объект и присвоение значения полю service_provider объект модуля LWP :: Authen :: OAuth2 :: ServiceProvider , который может нуждаться также в его параметрах, таких как scope, чтобы определить, для какого семейства API вы хотите авторизоваться, и в зависимости от этого client_type.

Теперь Google не является сервисным провайдером без имени, поэтому уже существует предварительно собранный модуль ServiceProvider, явно для API Google: 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"
);

Свернув дальнейшее описание здесь и отправивзапрос со встроенным объектом LWP :: UserAgent Я все еще получил ошибку 401 UNAUTHENTICATED, которая меня сильно смутила.Поэтому, когда я прочитал документацию, я не знаю, во сколько я перешёл эту крошечную строку в главе client_types ServiceProvider :: Google :

Сервисная учетная запись

Этот client_type предназначен для приложений, которые входят в учетную запись разработчика с использованием учетных данных разработчика.См. https://developers.google.com/accounts/docs/OAuth2ServiceAccount для документации Google.

Это еще не поддерживается и потребует использования веб-токенов JSON для поддержки.

Да, это как-то сбивает с толкуиспользование всего семейства LWP: Authen :: OAuth для доступа к API Firebase, поскольку почти все они имеют client_type => "service_account".Теперь у меня есть крайний срок для моего проекта, и я не могу дождаться, когда модуль будет расширен, или его расширение превысит мои навыки Perl.

Но между слезами отчаяния всегда появляется проблеск надежды, как я обнаружил эту страницу документации Google с живым приложением о том, что можно использовать JSON WebТокен как токен на предъявителя.В поисках этого я нашел более одного решения Perl для генерации JWT из JSON, таких как учетная запись службы, а также этот очень полезный ответ Stackoverflow, который показал мне выход из этой проблемы.

...