# Добавление кнопки входа через HF в ваше Space

Вы можете включить встроенный процесс входа в ваш Space, создав и привязав приложение [OAuth/OpenID connect](https://developer.okta.com/blog/2019/10/21/illustrated-guide-to-oauth-and-oidc), чтобы пользователи могли входить со своим аккаунтом HF.

Это открывает новые сценарии использования для вашего Space. Например, в сочетании с [Storage Buckets](https://huggingface.co/docs/hub/storage-buckets) Space для генеративного ИИ может позволять пользователям входить в систему, чтобы получить доступ к своим предыдущим результатам генерации, доступным только им.

> [!TIP]
> В этом руководстве описан процесс интеграции кнопки *Sign-In with HF* в любое Space. Если вам нужен быстрый и простой способ реализовать это в Space на базе **Gradio**, обратите внимание на его [встроенную интеграцию](https://www.gradio.app/guides/sharing-your-app#o-auth-login-via-hugging-face).

> [!TIP]
> Вы также можете использовать поток HF OAuth для создания сценария «Вход через HF» на любом сайте или в любом приложении, вне Spaces. [Прочитайте нашу общую страницу об OAuth](./oauth).

## Создание приложения OAuth

Вам нужно лишь добавить `hf_oauth: true` в метаданные вашего Space в файле `README.md`.

Вот пример метаданных для пространства Gradio:

```yaml
title: Gradio Oauth Test
emoji: 🏆
colorFrom: pink
colorTo: pink
sdk: gradio
sdk_version: 3.40.0
python_version: 3.10.6
app_file: app.py

hf_oauth: true
# optional, default duration is 8 hours/480 minutes. Max duration is 30 days/43200 minutes.
hf_oauth_expiration_minutes: 480
# optional, see "Scopes" below. "openid profile" is always included.
hf_oauth_scopes:
 - read-repos
 - gated-repos
 - write-repos
 - manage-repos
 - inference-api
# optional, restrict access to members of specific organizations
hf_oauth_authorized_org: ORG_NAME
hf_oauth_authorized_org:
  - ORG_NAME1
  - ORG_NAME2
```

Подробнее можно узнать в [справочнике по конфигурации](./spaces-config-reference).

Это добавит следующие [переменные окружения](https://huggingface.co/docs/hub/spaces-overview#built-in-environment-variables) в ваше пространство:

- `OAUTH_CLIENT_ID`: идентификатор клиента вашего OAuth-приложения (публичный)
- `OAUTH_CLIENT_SECRET`: секрет клиента вашего OAuth-приложения
- `OAUTH_SCOPES`: области доступа, доступные вашему OAuth-приложению.
- `OPENID_PROVIDER_URL`: URL провайдера OpenID. Метаданные OpenID будут доступны по адресу [`{OPENID_PROVIDER_URL}/.well-known/openid-configuration`](https://huggingface.co/.well-known/openid-configuration).

Как и в случае с любой другой переменной окружения, вы можете использовать их в коде, например, с помощью `os.getenv("OAUTH_CLIENT_ID")`.

## URL-адреса перенаправления

Вы можете использовать любой URL перенаправления, если он указывает на ваше Space.

Обратите внимание, что `SPACE_HOST` [доступен](https://huggingface.co/docs/hub/spaces-overview#built-in-environment-variables) в качестве переменной окружения.

Например, в качестве URI перенаправления можно использовать `https://{SPACE_HOST}/login/callback`.

## Области видимости

Следующие области действия всегда включаются для Spaces:

- `openid`: Получение ID-токена в дополнение к access-токену.
- `profile`: чтение информации из профиля пользователя (имя пользователя, аватар и т. д.)

Эти области действия являются необязательными и могут быть добавлены путём установки `hf_oauth_scopes` в метаданных вашего Space:

- `email`: чтение адреса электронной почты пользователя.
- `read-billing`: позволяет узнать, настроен ли у пользователя способ оплаты.
- `read-memberships`: чтение списков организаций, в которых состоит пользователь, и его роли в каждой из них. Это не предоставляет доступ к настройкам или ресурсам организаций.
- `read-repos`: чтение личных репозиториев пользователя.
- `gated-repos`: чтение содержимого публичных репозиториев с ограниченным доступом, к которым у пользователя есть права. В отличие от `read-repos`, это не предоставляет доступ к частным репозиториям.
- `contribute-repos`: создание репозиториев и доступ к тем, которые были созданы этим приложением. Доступ к другим репозиториям невозможен, если не предоставлены дополнительные разрешения.
- `write-repos`: чтение и запись личных репозиториев пользователя.
- `manage-repos`: Полное управление личными репозиториями пользователя, включая их создание и удаление.
- `read-collections`: чтение личных коллекций пользователя.
- `write-collections`: чтение и запись личных коллекций пользователя, включая их создание и удаление.
- `inference-api`: Выполнение запросов на инференс к [Inference Providers](https://huggingface.co/docs/inference-providers/index) от имени пользователя.
- `read-endpoints`: Просмотр [Inference Endpoints](https://huggingface.co/docs/inference-endpoints/index) пользователя и выполнение запросов на инференс от его имени.
- `write-endpoints`: управление Inference Endpoints пользователя, включая их создание и удаление. Включает доступ `read-endpoints`.
- `jobs`: Запуск [jobs](https://huggingface.co/docs/huggingface_hub/main/en/guides/jobs)
- `webhooks`: Управление [webhooks](https://huggingface.co/docs/huggingface_hub/main/en/guides/webhooks)
- `write-discussions`: открытие обсуждений и Pull Requests от имени пользователя, а также взаимодействие с обсуждениями (включая реакции, публикацию/редактирование комментариев, закрытие обсуждений и т. д.). Для открытия Pull Requests в частных репозиториях также требуется запросить область `read-repos`.

## Доступ к ресурсам организации

По умолчанию приложению oauth не требуется доступ к ресурсам организации.

Однако некоторые области, такие как `read-repos` или `read-billing`, также применяются к организациям.

Пользователь может выбрать, какие организации предоставить доступ при авторизации приложения. Если вам требуется доступ к конкретной организации, вы можете добавить `orgIds=ORG_ID` в качестве параметра запроса к URL авторизации OAuth. Вам необходимо заменить `ORG_ID` на идентификатор организации, который доступен в поле `organizations.sub` ответа userinfo.

## Добавление кнопки в ваше Space

Теперь у вас есть вся информация, необходимая для добавления кнопки «Войти через HF» в ваше Space. Некоторые библиотеки ([Python](https://github.com/lepture/authlib), [NodeJS](https://github.com/panva/node-openid-client)) могут помочь вам реализовать протокол OpenID/OAuth.

Gradio и huggingface.js также обеспечивают **встроенную поддержку**, что делает реализацию кнопки Sign-in with HF простой задачей; с соответствующими руководствами можно ознакомиться в документации по [gradio](https://www.gradio.app/guides/sharing-your-app#o-auth-login-via-hugging-face) и по [huggingface.js](https://huggingface.co/docs/huggingface.js/hub/README#oauth-login).

По сути, вам нужно:

- Перенаправьте пользователя на `https://huggingface.co/oauth/authorize?redirect_uri={REDIRECT_URI}&scope=openid%20profile&client_id={CLIENT_ID}&state={STATE}`, где `STATE` — это случайная строка, которую вам потребуется проверить позже.
- Обрабатывайте callback по адресу `/auth/callback` или `/login/callback` (или по собственному URL callback) и проверяйте параметр `state`.
- Используйте параметр запроса `code`, чтобы получить токен доступа и токен идентификатора с `https://huggingface.co/oauth/token` (POST-запрос с `client_id`, `code`, `grant_type=authorization_code` и `redirect_uri` в качестве данных формы, а также с заголовком `Authorization: Basic {base64(client_id:client_secret)}`).

> [!WARNING]
> На кнопке следует использовать `target=_blank`, чтобы страница входа открывалась в новой вкладке, если только вы не запускаете пространство вне его `iframe`. В противном случае в некоторых браузерах могут возникать проблемы с cookie.

## Примеры:

- [Тестовое приложение Gradio](https://huggingface.co/spaces/Wauplin/gradio-oauth-test)
- [HuggingChat (NodeJS/SvelteKit)](https://huggingface.co/spaces/huggingchat/chat-ui)
- [Виджеты инференса (Auth.js/SvelteKit)](https://huggingface.co/spaces/huggingfacejs/inference-widgets) используют область `inference-api` для выполнения запросов инференса от имени пользователя.
- [Клиентская часть в статическом пространстве (huggingface.js)](https://huggingface.co/spaces/huggingfacejs/client-side-oauth) — очень простой пример на JavaScript.

Пример кода на JS:

```js
import { oauthLoginUrl, oauthHandleRedirectIfPresent } from "@huggingface/hub";

const oauthResult = await oauthHandleRedirectIfPresent();

if (!oauthResult) {
  // If the user is not logged in, redirect to the login page
  window.location.href = await oauthLoginUrl();
}

// You can use oauthResult.accessToken, oauthResult.userInfo among other things
console.log(oauthResult);
```

