# Безпека - перші кроки { #security-first-steps }

Уявімо, що ваш **backend** API працює на певному домені.

А **frontend** - на іншому домені або в іншому шляху того ж домену (або у мобільному застосунку).

І ви хочете, щоб frontend міг автентифікуватися в backend, використовуючи ім'я користувача та пароль.

Ми можемо використати **OAuth2**, щоб збудувати це з **FastAPI**.

Але заощадимо вам час на читання всієї довгої специфікації, щоб знайти лише потрібні дрібниці.

Скористаймося інструментами, які надає **FastAPI**, щоб обробляти безпеку.

## Як це виглядає { #how-it-looks }

Спочатку просто запустімо код і подивімося, як він працює, а потім повернемося, щоб розібратися, що відбувається.

## Створіть `main.py` { #create-main-py }

Скопіюйте приклад у файл `main.py`:

{* ../../docs_src/security/tutorial001_an_py310.py *}

## Запустіть { #run-it }

/// info | Інформація

Пакет [`python-multipart`](https://github.com/Kludex/python-multipart) автоматично встановлюється з **FastAPI**, коли ви виконуєте команду `pip install "fastapi[standard]"`.

Однак, якщо ви використовуєте команду `pip install fastapi`, пакет `python-multipart` за замовчуванням не включено.

Щоб встановити його вручну, переконайтеся, що ви створили [віртуальне оточення](../../virtual-environments.md), активували його, а потім встановили:

```console
$ pip install python-multipart
```

Це тому, що **OAuth2** використовує «form data» для надсилання `username` та `password`.

///

Запустіть приклад:

<div class="termy">

```console
$ fastapi dev

<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```

</div>

## Перевірте { #check-it }

Перейдіть до інтерактивної документації: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs).

Ви побачите щось подібне:

<img src="/img/tutorial/security/image01.png">

/// check | Кнопка Authorize!

У вас уже є нова блискуча кнопка «Authorize».

А ваша *операція шляху* має маленький замок у правому верхньому куті, на який можна натиснути.

///

Якщо натиснути її, з’явиться маленька форма авторизації, щоб ввести `username` і `password` (та інші необов’язкові поля):

<img src="/img/tutorial/security/image02.png">

/// note | Примітка

Неважливо, що ви введете у форму, поки що це не спрацює. Але ми скоро це доробимо.

///

Звісно, це не frontend для кінцевих користувачів, але це чудовий інструмент для інтерактивної документації всього вашого API.

Ним може користуватися команда frontend (якою можете бути і ви самі).

Ним можуть користуватися сторонні застосунки та системи.

І ним також можете користуватися ви самі, щоб налагоджувати, перевіряти та тестувати той самий застосунок.

## Потік паролю { #the-password-flow }

Тепер повернімося трохи назад і розберімося, що це все таке.

`password` «flow» - це один зі способів («flows»), визначених в OAuth2, для обробки безпеки та автентифікації.

OAuth2 був спроєктований так, щоб backend або API могли бути незалежними від сервера, який автентифікує користувача.

Але в нашому випадку той самий застосунок **FastAPI** оброблятиме і API, і автентифікацію.

Тож розгляньмо це у спрощеному вигляді:

- Користувач вводить `username` і `password` у frontend і натискає `Enter`.
- Frontend (у браузері користувача) надсилає ці `username` і `password` на специфічну URL-адресу нашого API (оголошену як `tokenUrl="token"`).
- API перевіряє ці `username` і `password` та повертає «токен» (ми ще нічого з цього не реалізували).
    - «Токен» - це просто строка з деяким вмістом, який ми можемо пізніше використати, щоб перевірити цього користувача.
    - Зазвичай токен налаштований на завершення строку дії через певний час.
        - Тож користувачу доведеться знову увійти пізніше.
        - І якщо токен викрадуть, ризик менший. Це не як постійний ключ, який працюватиме завжди (у більшості випадків).
- Frontend тимчасово зберігає цей токен десь.
- Користувач клікає у frontend, щоб перейти до іншого розділу вебзастосунку.
- Frontend має отримати ще дані з API.
    - Але для того конкретного кінцевого пункту потрібна автентифікація.
    - Тож, щоб автентифікуватися в нашому API, він надсилає заголовок `Authorization` зі значенням `Bearer ` плюс токен.
    - Якщо токен містить `foobar`, вміст заголовка `Authorization` буде: `Bearer foobar`.

## `OAuth2PasswordBearer` у **FastAPI** { #fastapis-oauth2passwordbearer }

**FastAPI** надає кілька інструментів на різних рівнях абстракції, щоб реалізувати ці функції безпеки.

У цьому прикладі ми використаємо **OAuth2** з потоком **Password**, використовуючи токен **Bearer**. Це робиться за допомогою класу `OAuth2PasswordBearer`.

/// info | Інформація

«Bearer»-токен - не єдиний варіант.

Але це найкращий для нашого сценарію.

І, можливо, найкращий для більшості сценаріїв, якщо ви не експерт з OAuth2 і точно не знаєте, чому інша опція краще відповідає вашим потребам.

У такому разі **FastAPI** теж надає інструменти, щоб це збудувати.

///

Коли ми створюємо екземпляр класу `OAuth2PasswordBearer`, ми передаємо параметр `tokenUrl`. Цей параметр містить URL, який клієнт (frontend у браузері користувача) використовуватиме, щоб надіслати `username` і `password` для отримання токена.

{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *}

/// tip | Порада

Тут `tokenUrl="token"` відноситься до відносної URL-адреси `token`, яку ми ще не створили. Оскільки це відносна URL-адреса, вона еквівалентна `./token`.

Тому, якщо ваш API розміщений на `https://example.com/`, це буде `https://example.com/token`. А якщо на `https://example.com/api/v1/`, тоді це буде `https://example.com/api/v1/token`.

Використання відносної URL-адреси важливе, щоб ваша програма продовжувала працювати навіть у просунутому сценарії, як-от [За представником](../../advanced/behind-a-proxy.md).

///

Цей параметр не створює той endpoint / *операцію шляху*, а декларує, що URL `/token` буде тим, який клієнт має використовувати, щоб отримати токен. Ця інформація використовується в OpenAPI, а потім - у системах інтерактивної документації API.

Незабаром ми також створимо фактичну операцію шляху.

/// info | Інформація

Якщо ви дуже строгий «Pythonista», вам може не подобатися стиль імені параметра `tokenUrl` замість `token_url`.

Це тому, що використано ту саму назву, що і в специфікації OpenAPI. Тож якщо вам потрібно буде дослідити ці схеми безпеки глибше, ви зможете просто скопіювати та вставити її, щоб знайти більше інформації.

///

Змінна `oauth2_scheme` - це екземпляр `OAuth2PasswordBearer`, але це також і «викликаємий» об’єкт.

Його можна викликати так:

```Python
oauth2_scheme(some, parameters)
```

Тож його можна використовувати з `Depends`.

### Використання { #use-it }

Тепер ви можете передати `oauth2_scheme` як залежність через `Depends`.

{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *}

Ця залежність надасть `str`, який буде присвоєний параметру `token` *функції операції шляху*.

**FastAPI** знатиме, що може використати цю залежність, щоб визначити «схему безпеки» в схемі OpenAPI (і в автоматичній документації API).

/// info | Технічні деталі

**FastAPI** знатиме, що може використати клас `OAuth2PasswordBearer` (оголошений у залежності), щоб визначити схему безпеки в OpenAPI, тому що він наслідує `fastapi.security.oauth2.OAuth2`, який своєю чергою наслідує `fastapi.security.base.SecurityBase`.

Усі утиліти безпеки, які інтегруються з OpenAPI (і автоматичною документацією API), наслідують `SecurityBase`. Так **FastAPI** розуміє, як інтегрувати їх в OpenAPI.

///

## Що відбувається { #what-it-does }

Вона шукатиме в запиті заголовок `Authorization`, перевірить, чи його значення - це `Bearer ` плюс деякий токен, і поверне токен як `str`.

Якщо заголовка `Authorization` немає або значення не містить токена `Bearer `, вона одразу відповість помилкою зі статус-кодом 401 (`UNAUTHORIZED`).

Вам навіть не потрібно перевіряти, чи існує токен, щоб повернути помилку. Ви можете бути певні: якщо ваша функція виконується, у параметрі токена буде `str`.

Ви вже можете спробувати це в інтерактивній документації:

<img src="/img/tutorial/security/image03.png">

Ми ще не перевіряємо дійсність токена, але це вже початок.

## Підсумок { #recap }

Отже, лише 3-4 додатковими рядками ви вже маєте деяку примітивну форму безпеки.
