Развертывание веб-приложения с JWT-авторизацией в Yandex API Gateway и аутентификацией в Firebase
- Подготовьте облако к работе
- Создайте проект и настройте Google OAuth в Google Cloud
- Настройте аутентификацию в Firebase
- Завершите настройку ресурсов Google
- Создайте API-шлюз
- Подготовьте файлы веб-приложения
- Разверните ресурсы Yandex Cloud и загрузите веб-приложение в бакет Object Storage
- Протестируйте работу созданного приложения
- Как удалить созданные ресурсы
В этом руководстве вы узнаете, как реализовать аутентификацию и авторизацию в вашем веб-приложении на основе протоколов OAuth 2.0
- Внешнего сервиса аутентификации Firebase.
- Простого REST API, развернутого в виде API Gateway.
- Статического веб-сайта, развернутого в бакете Yandex Object Storage.
Чтобы развернуть веб-приложение:
- Подготовьте облако к работе.
- Создайте проект и настройте Google OAuth в Google Cloud.
- Настройте аутентификацию в Firebase.
- Завершите настройку ресурсов Google.
- Создайте API-шлюз.
- Подготовьте файлы веб-приложения.
- Разверните ресурсы Yandex Cloud и загрузите веб-приложение в бакет.
- Проверьте работу созданного приложения.
Если созданные ресурсы больше не нужны, удалите их.
Подготовьте облако к работе
Зарегистрируйтесь в Yandex Cloud и создайте платежный аккаунт:
- Перейдите в консоль управления
, затем войдите в Yandex Cloud или зарегистрируйтесь. - На странице Yandex Cloud Billing
убедитесь, что у вас подключен платежный аккаунт, и он находится в статусеACTIVE
илиTRIAL_ACTIVE
. Если платежного аккаунта нет, создайте его и привяжите к нему облако.
Если у вас есть активный платежный аккаунт, вы можете создать или выбрать каталог, в котором будет работать ваша инфраструктура, на странице облака
Подробнее об облаках и каталогах.
Необходимые платные ресурсы
В стоимость поддержки инфраструктуры для работы веб-приложения входят:
- Плата за хранение данных в бакете и операции с ними (см. тарифы Object Storage).
- Плата за использование API-шлюза (см. тарифы API Gateway).
Создайте проект и настройте Google OAuth в Google Cloud
Настройте Google OAuth:
- Авторизуйтесь в Google Cloud Console
и создайте новый проект. - На вкладке API & Services → OAuth consent screen выберите тип приложения
External
и нажмите кнопку Create. - В разделе OAuth consent screen укажите название приложения и ваш адрес электронной почты в полях User support email и Developer contact information. Нажмите кнопку Save and continue.
- В разделе Scopes нажмите кнопку Add or Remove Scopes и добавьте скоупы
openid
,/auth/userinfo.email
и/auth/userinfo.profile
. Нажмите Update → Save and continue. - В разделе Test users укажите ваш адрес электронной почты. Завершите создание приложения.
- На вкладке API & Services → Credentials нажмите кнопку Create credential и выберите
OAuth client ID
. В качестве типа приложения укажитеWeb application
. - Подтвердите создание приложения и сохраните
Client ID
иClient secret
.
Настройте аутентификацию в Firebase
- Авторизуйтесь в Firebase Console
и создайте новый проект. - В разделе Authentication → Sign-in method → Custom providers выберите
OpenID Connect
. - Подтвердите выбор
OpenID Connect
. - Укажите имя провайдера,
Client ID
иClient secret
, которые получили на предыдущем шаге, а также заполните поле Issuer — для Google OAuth оно должно иметь значениеhttps://accounts.google.com
. - Сохраните
Callback URL
и завершите настройку OpenID.
Завершите настройку ресурсов Google
Google Console:
- На вкладке API & Services → Credentials нажмите на имя созданного клиента.
- В список Authorized redirect URIs добавьте Callback URL из Firebase, который получили на предыдущем шаге. Сохраните внесенные изменения.
Firebase:
- Перейдите в раздел Project Overview → Project settings.
- На вкладке
General
создайте веб-приложение. Укажите имя приложения и нажмите кнопку Register App. - Сохраните сгенерированную в блоке
firebaseConfig
конфигурацию приложения.
Создайте API-шлюз
-
В консоли управления
выберите каталог, в котором необходимо создать API-шлюз. -
В списке сервисов выберите API Gateway.
-
Нажмите кнопку Создать API-шлюз.
-
В поле Имя введите
jwt-api-gw
. -
В блок Спецификация добавьте спецификацию:
openapi: 3.0.0 info: title: Sample API version: 1.0.0 paths: /: get: x-yc-apigateway-integration: type: http url: https://oauth2.googleapis.com/tokeninfo method: GET query: id_token: '{token}' parameters: - name: token in: query required: true schema: type: string security: - OpenIdAuthorizerScheme: [ ] components: securitySchemes: OpenIdAuthorizerScheme: type: openIdConnect x-yc-apigateway-authorizer: type: jwt jwksUri: https://www.googleapis.com/oauth2/v3/certs identitySource: in: query name: token issuers: - https://accounts.google.com requiredClaims: - email
-
Нажмите кнопку Создать.
Если у вас еще нет интерфейса командной строки Yandex Cloud, установите и инициализируйте его.
По умолчанию используется каталог, указанный в профиле CLI. Вы можете указать другой каталог с помощью параметра --folder-name
или --folder-id
.
-
Сохраните следующую спецификацию в файл
jwt-auth.yaml
:openapi: 3.0.0 info: title: Sample API version: 1.0.0 paths: /: get: x-yc-apigateway-integration: type: http url: https://oauth2.googleapis.com/tokeninfo method: GET query: id_token: '{token}' parameters: - name: token in: query required: true schema: type: string security: - OpenIdAuthorizerScheme: [ ] components: securitySchemes: OpenIdAuthorizerScheme: type: openIdConnect x-yc-apigateway-authorizer: type: jwt jwksUri: https://www.googleapis.com/oauth2/v3/certs identitySource: in: query name: token issuers: - https://accounts.google.com requiredClaims: - email
-
Выполните команду:
yc serverless api-gateway create \ --name jwt-api-gw \ --spec=jwt-auth.yaml
Где:
--name
— имя API-шлюза.--spec
— файл со спецификацией.
Результат:
done (29s) id: d5dug9gkmu187i******** folder_id: b1g55tflru0ek7******** created_at: "2020-06-17T09:20:22.929Z" name: jwt-api-gw status: ACTIVE domain: d5dug9gkmu187i********.apigw.yandexcloud.net log_group_id: ckghq1hm19********
Если у вас еще нет Terraform, установите его и настройте провайдер Yandex Cloud.
-
Опишите в конфигурационном файле параметры API-шлюза:
resource "yandex_api_gateway" "jwt-api-gateway" { name = "jwt-api-gw" spec = <<-EOT openapi: 3.0.0 info: title: Sample API version: 1.0.0 paths: /: get: x-yc-apigateway-integration: type: http url: https://oauth2.googleapis.com/tokeninfo method: GET query: id_token: '{token}' parameters: - name: token in: query required: true schema: type: string security: - OpenIdAuthorizerScheme: [ ] components: securitySchemes: OpenIdAuthorizerScheme: type: openIdConnect x-yc-apigateway-authorizer: type: jwt jwksUri: https://www.googleapis.com/oauth2/v3/certs identitySource: in: query name: token issuers: - https://accounts.google.com requiredClaims: - email EOT }
Где:
name
— имя API-шлюза.spec
— спецификация API-шлюза.
Более подробную информацию о параметрах ресурса
yandex_api_gateway
в Terraform, см. в документации провайдера . -
Создайте ресурсы:
-
В терминале перейдите в папку, где вы отредактировали конфигурационный файл.
-
Проверьте корректность конфигурационного файла с помощью команды:
terraform validate
Если конфигурация является корректной, появится сообщение:
Success! The configuration is valid.
-
Выполните команду:
terraform plan
В терминале будет выведен список ресурсов с параметрами. На этом этапе изменения не будут внесены. Если в конфигурации есть ошибки, Terraform на них укажет.
-
Примените изменения конфигурации:
terraform apply
-
Подтвердите изменения: введите в терминале слово
yes
и нажмите Enter.
-
После этого в указанном каталоге будет создан API-шлюз.
Чтобы создать API-шлюз, воспользуйтесь методом REST API create для ресурса ApiGateway или вызовом gRPC API ApiGatewayService/Create.
Подготовьте файлы веб-приложения
-
Клонируйте репозиторий
с исходным кодом приложения:git clone https://github.com/yandex-cloud-examples/yc-serverless-apigw-jwt-authorizer-firebase.git
-
Откройте с помощью текстового редактора файл
src/App.js
и укажите параметры:firebaseConfig
— конфигурация приложения Firebase, которую вы сохранили при завершении настройки ресурсов Google.providerId
— идентификатор созданного ранее в Firebase провайдера OpenID Connect в форматеoidc.<имя_провайдера>
.apiGwDomain
— служебный домен созданного ранее API-шлюза.
-
Установите Node.js
и менеджер пакетов npm. Менеджер пакетов будет установлен автоматически при установке Node.js. -
В папке с вашим приложением:
-
Установите react-scripts в ваш проект и добавьте его в зависимости (devDependencies) в файле
package.json
:npm install react-scripts --save-dev
-
Запустите сборку приложения:
npm run build
Результат:
File sizes after gzip: 96.05 kB build\static\js\main.de7af71f.js 672 B build\static\css\main.021818e9.css The project was built assuming it is hosted at /. You can control this with the homepage field in your package.json. The build folder is ready to be deployed.
-
Разверните ресурсы Yandex Cloud и загрузите веб-приложение в бакет Object Storage
Разверните статический веб-сайт.
-
Создайте бакет Object Storage:
Консоль управленияCLITerraformAPI- В консоли управления
выберите каталог, в котором хотите создать бакет. - Выберите сервис Object Storage.
- Нажмите кнопку Создать бакет.
- На странице создания бакета:
- Введите имя бакета —
bucket-for-tutorial
. - В поле Доступ на чтение объектов выберите
Публичный
. - Нажмите кнопку Создать бакет для завершения операции.
- Введите имя бакета —
Если у вас еще нет интерфейса командной строки Yandex Cloud, установите и инициализируйте его.
По умолчанию используется каталог, указанный в профиле CLI. Вы можете указать другой каталог с помощью параметра
--folder-name
или--folder-id
.-
Выполните следующую команду:
yc storage bucket create \ --name bucket-for-tutorial \ --public-read
Где:
--name
— имя бакета.--public-read
— флаг для включения публичного доступа на чтение объектов в бакете.
Результат:
name: bucket-for-tutorial folder_id: b1gmit33******** anonymous_access_flags: ... versioning: VERSIONING_DISABLED acl: {} created_at: "2023-06-08T11:57:49.898024Z"
Если у вас еще нет Terraform, установите его и настройте провайдер Yandex Cloud.
-
Опишите в конфигурационном файле параметры необходимых ресурсов:
... resource "yandex_iam_service_account" "sa" { name = "<имя_сервисного_аккаунта>" } resource "yandex_resourcemanager_folder_iam_member" "sa-editor" { folder_id = "<идентификатор_каталога>" role = "storage.editor" member = "serviceAccount:${yandex_iam_service_account.sa.id}" } resource "yandex_iam_service_account_static_access_key" "sa-static-key" { service_account_id = yandex_iam_service_account.sa.id description = "static access key for object storage" } resource "yandex_storage_bucket" "test" { access_key = yandex_iam_service_account_static_access_key.sa-static-key.access_key secret_key = yandex_iam_service_account_static_access_key.sa-static-key.secret_key bucket = "bucket-for-tutorial" acl = "public-read" } ...
Где:
yandex_iam_service_account
— описание сервисного аккаунта, который создаст бакет и будет работать с ним:name
— имя сервисного аккаунта.
yandex_storage_bucket
— описание бакета:bucket
— имя бакета.acl
— настройки доступа к бакету.
Более подробную информацию о параметрах ресурса
yandex_storage_bucket
в Terraform см. в документации провайдера . -
Создайте ресурсы:
-
В терминале перейдите в папку, где вы отредактировали конфигурационный файл.
-
Проверьте корректность конфигурационного файла с помощью команды:
terraform validate
Если конфигурация является корректной, появится сообщение:
Success! The configuration is valid.
-
Выполните команду:
terraform plan
В терминале будет выведен список ресурсов с параметрами. На этом этапе изменения не будут внесены. Если в конфигурации есть ошибки, Terraform на них укажет.
-
Примените изменения конфигурации:
terraform apply
-
Подтвердите изменения: введите в терминале слово
yes
и нажмите Enter.
-
После этого в указанном каталоге будет создан бакет.
Чтобы создать бакет, воспользуйтесь методом REST API create для ресурса Bucket, вызовом gRPC API BucketService/Create или методом S3 API create.
- В консоли управления
-
Загрузите объекты в бакет Object Storage:
Консоль управления- В консоли управления
выберите каталог, в который нужно загрузить объекты. - Выберите сервис Object Storage.
- Нажмите на бакет
bucket-for-tutorial
. - Нажмите кнопку Загрузить и выберите сгенерированные ранее объекты в папке
build
. - Консоль управления отобразит все объекты, выбранные для загрузки, и предложит для каждого из них выбрать класс хранилища. Класс хранилища по умолчанию определяется настройкой бакета.
- Нажмите кнопку Загрузить.
- Обновите страницу.
В консоли управления информация о количестве объектов в бакете и занятом месте обновляется с задержкой в несколько минут.
- В консоли управления
-
Настройте хостинг статического сайта:
Консоль управленияCLITerraformAPI- В консоли управления
перейдите в бакетbucket-for-tutorial
. - На панели слева выберите Настройки.
- На вкладке Веб-сайт:
- Выберите
Хостинг
. - В поле Главная страница укажите абсолютный путь к файлу главной страницы сайта —
index.html
. - В поле Страница ошибки укажите абсолютный путь к файлу, который будет отображаться при ошибках 4хх —
error.html
.
- Выберите
- Нажмите кнопку Сохранить.
- В поле Ссылка скопируйте адрес вашего сайта.
Если у вас еще нет интерфейса командной строки Yandex Cloud, установите и инициализируйте его.
По умолчанию используется каталог, указанный в профиле CLI. Вы можете указать другой каталог с помощью параметра
--folder-name
или--folder-id
.-
Создайте файл
setup.json
с настройками хостинга в формате JSON:{ "index": "index.html", "error": "error404.html" }
Где:
index
— абсолютный путь к файлу главной страницы сайта.error
— абсолютный путь к файлу, который будет отображаться пользователю при ошибках 4хх.
-
Выполните команду:
yc storage bucket update --name bucket-for-tutorial \ --website-settings-from-file setup.json
Где:
--name
— имя бакета.--website-settings-from-file
— путь к файлу с настройками переадресации.
Результат:
name: my-bucket folder_id: b1gjs8dck******** default_storage_class: STANDARD versioning: VERSIONING_SUSPENDED max_size: "10737418240" acl: {} created_at: "2022-12-14T08:42:16.273717Z"
Если у вас еще нет Terraform, установите его и настройте провайдер Yandex Cloud.
Чтобы настроить переадресацию всех запросов:
-
Откройте файл конфигурации Terraform и добавьте параметр
redirect_all_requests_to
в описание ресурсаyandex_storage_bucket
:... resource "yandex_storage_bucket" "test" { access_key = yandex_iam_service_account_static_access_key.sa-static-key.access_key secret_key = yandex_iam_service_account_static_access_key.sa-static-key.secret_ke bucket = "bucket-for-tutorial" acl = "public-read" website { index_document = "index.html" error_document = "error.html" } } ...
Где:
website
— параметры веб-сайта:index_document
— абсолютный путь к файлу главной страницы сайта. Обязательный параметр.error_document
— абсолютный путь к файлу, который будет отображаться пользователю при ошибках4хх
. Необязательный параметр.
Более подробную информацию о параметрах ресурса
yandex_storage_bucket
в Terraform см. в документации провайдера . -
Создайте ресурсы:
-
В терминале перейдите в папку, где вы отредактировали конфигурационный файл.
-
Проверьте корректность конфигурационного файла с помощью команды:
terraform validate
Если конфигурация является корректной, появится сообщение:
Success! The configuration is valid.
-
Выполните команду:
terraform plan
В терминале будет выведен список ресурсов с параметрами. На этом этапе изменения не будут внесены. Если в конфигурации есть ошибки, Terraform на них укажет.
-
Примените изменения конфигурации:
terraform apply
-
Подтвердите изменения: введите в терминале слово
yes
и нажмите Enter.
-
После этого в бакете будет настроен хостинг.
Чтобы настроить хостинг статического сайта, воспользуйтесь методом REST API update для ресурса Bucket, вызовом gRPC API BucketService/Update или методом S3 API upload.
- В консоли управления
-
Добавьте адрес вашего сайта в список допустимых доменов в Firebase:
- Перейдите в раздел Authentication → Settings → Authorized domains.
- Нажмите кнопку Add domain и вставьте скопированный адрес.
Протестируйте работу созданного приложения
- Обратитесь к статическому сайту по адресу, который получили при настройке хостинга, и нажмите кнопку Call API Gateway, не проходя авторизации. Убедитесь, что в ответ приходит ошибка
Got error: Request failed with status code 401
. - Чтобы авторизоваться на сайте, нажмите кнопку Log in.
- После авторизации снова нажмите кнопку Call API Gateway. Убедитесь, что вызов успешно обрабатывается и в ответ приходит информация об авторизованном пользователе.
Как удалить созданные ресурсы
Чтобы перестать платить за созданные ресурсы: