# Аутентифікація та авторизація (Authentication and authorization)

**Ідентифікація** - процедура, внаслідок виконання якої для суб'єкта ідентифікації виявляється його ідентифікатор, який однозначно визначає цього суб'єкта в інформаційній системі.

**Аутентифікація** - процедура автентифікації, наприклад автентифікація користувача шляхом порівняння введеного ним пароля з паролем, збереженим у базі даних.

**Авторизація** - надання певній особі чи групі осіб прав виконання певних дій.

*В англомовних джерелах ідентифікація не виділяється в окремий пункт: “Authentication is the process of **identifying** users and **validating** who they claim to be”.*

Скажімо, користувач хоче увійти до свого облікового запису Google. Google підходить найкраще, тому що там процедура входу явно розбита на кілька найпростіших етапів. Ось що при цьому відбувається:

* Спочатку система запитує логін, користувач його вказує, система розпізнає його як існуючий - це ідентифікація.
* Після цього Google просить ввести пароль, користувач його вводить, і система погоджується, що користувач, схоже, справжній, якщо пароль збігся, - це автентифікація.
* Швидше за все, Google додатково запитає ще й одноразовий код із SMS або програми. Якщо користувач і його правильно введе, система остаточно погодиться з тим, що він справжній власник акаунту, - це двофакторна автентифікація.
* Після цього система надасть користувачеві право читати листи у його поштовій скриньці і все в такому дусі – це авторизація.

Аутентифікація без попередньої ідентифікації позбавлена ​​сенсу - доки система не зрозуміє, справжність чого треба перевіряти, абсолютно безглуздо починати перевірку. Для початку треба представитися.

Ідентифікація без аутентифікації – це просто безглуздо. Тому що мало хто ввів існуючий у системі логін! Системі обов'язково треба впевнитись, що цей хтось знає ще й пароль. Але пароль могли підглянути або підібрати, тому краще підстрахуватися і запитати щось додаткове, що може бути відомо тільки користувачеві: наприклад, одноразовий код для підтвердження входу.

А ось авторизація без ідентифікації і тим більше автентифікації дуже можлива. Наприклад, у Google Документах можна публікувати документи так, щоб вони були доступні взагалі будь-кому. У цьому випадку ви як власник файлу побачите зверху напис, що говорить, що його читає невідомий єнот. Незважаючи на те, що єнот абсолютно непізнаний, система його все ж таки авторизувала - тобто видала право прочитати цей документ.

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

**Фреймворк HTTP-аутентифікації** (HTTP authentication framework)

[RFC 7235](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://datatracker.ietf.org/doc/html/rfc7235) визначає HTTP authentication framework, який може використовуватися сервером для виклику клієнтського запиту (to [challenge](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://developer.mozilla.org/en-US/docs/Glossary/challenge) a client request) та клієнтом для надання інформації для автентифікації. Порядок викликів та відповідей:

* Сервер відповідає клієнту зі статусом відповіді 401 (Unauthorized) і надає інформацію про те, як авторизуватися, з WWW-Authenticate response header, що містить як мінімум один виклик.
* Клієнт, який хоче аутентифікувати себе на сервері, може це зробити, включивши Authorization request header з обліковими даними (credentials).
* Зазвичай клієнт надає користувачеві запит пароля, а потім надсилає запит, включаючи правильний Authorization header.

[![https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication/http-auth-sequence-diagram.png](https://camo.githubusercontent.com/2cab9a16716d078e2a1f44474901d8b82f20ff6a62ef469375c7ffcee766c6d0/68747470733a2f2f646576656c6f7065722e6d6f7a696c6c612e6f72672f656e2d55532f646f63732f5765622f485454502f41757468656e7469636174696f6e2f687474702d617574682d73657175656e63652d6469616772616d2e706e67)](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://camo.githubusercontent.com/2cab9a16716d078e2a1f44474901d8b82f20ff6a62ef469375c7ffcee766c6d0/68747470733a2f2f646576656c6f7065722e6d6f7a696c6c612e6f72672f656e2d55532f646f63732f5765622f485454502f41757468656e7469636174696f6e2f687474702d617574682d73657175656e63652d6469616772616d2e706e67)

**Популярні методи аутентифікації**

* Перевірка справжності на основі пароля ( **Password-based authentication** ) - це простий метод автентифікації, що вимагає введення пароля для підтвердження особистості користувача.
* Безпарольна автентифікація ( **Passwordless authentication** ) - це коли користувач перевіряється за допомогою одноразового ПІН-у (OTP - One-time pins) або magic link, доставленої на зареєстровану адресу електронної пошти або номер телефону;
* Для двофакторної аутентифікації/багатофакторної аутентифікації ( **2FA/MFA** ) потрібно більше рівня безпеки, наприклад додатковий PIN-код або контрольне питання, для ідентифікації користувача та надання доступу до системи;
* Єдиний вхід ( **SSO** ) дозволяє користувачам отримувати доступ до кількох програм з одним набором облікових даних;
* Соціальна аутентифікація ( **Social authentication** ) перевіряє та аутентифікує користувачів з існуючими обліковими даними на платформах соціальних мереж.
* Біометрія ( [**Biometrics**](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://hackernoon.com/biometric-authentication-working-methods-and-use-cases-3z2a377p) ) - користувач пред'являє відбиток пальця або скан очі, щоб отримати доступ до системи.

**Популярні методи авторизації**

* Управління доступом на основі ролей ( **RBAC - Role-based access controls** ) може бути реалізовано для управління привілеями від системи до системи та від користувача до системи.
* Веб-токен JSON ( [**JWT – JSON web token**](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://gist.github.com/zmts/802dc9c3510d79fd40f9dc38a12bccfc) ) – це відкритий стандарт для безпечної передачі даних між сторонами, а користувачі авторизуються за допомогою пари відкритий/закритий ключ.
* **SAML** – це стандартний формат єдиного входу (SSO), в якому автентифікаційна інформація передається через XML-документи із цифровим підписом.
* Авторизація [**OpenID**](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://habr.com/ru/company/nixys/blog/566910/) перевіряє особу користувача на основі аутентифікації сервера авторизації;
* [**OAuth**](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://betterprogramming.pub/the-complete-guide-to-oauth-2-0-and-openid-connect-protocols-35ebc1cbc11a) дозволяє API аутентифікувати та отримувати доступ до запитаної системи або ресурсу.

**Аутентифікація на основі сесій**

Протокол HTTP не відстежує стану, і, якщо ми автентифікуємо користувача за допомогою імені та пароля, наша програма не буде знати, чи це людина, що і в попередньому запиті. Нам доведеться аутентифікувати знову. При кожному запиті HTTP нічого не знає про те, що відбувалося до цього, він лише передає запит. Так що, якщо вам потрібні особисті дані, доведеться знову логінуватися, щоб програма знала, що це точно ви. Може сильно дратувати.

Щоб позбутися цієї незручності, вигадали аутентифікацію на основі сесій/кук, за допомогою яких реалізували відстеження станів (stateful). Це означає, що автентифікаційний запис або сесія мають зберігатися і на сервері, і на клієнті. Сервер повинен відстежувати активні сесії у базі даних чи пам'яті, але в фронтенді створюється кука, у якій зберігається ідентифікатор сесії. Це автентифікація на основі куки, найпоширеніший і найвідоміший метод, який використовується вже давно.

Процедура аутентифікації на основі сесій:

* Користувач вводить у браузері своє ім'я та пароль, після чого клієнтська програма надсилає на сервер запит.
* Сервер перевіряє користувача, аутентифікує його, шле додатку унікальний токен (зберігши його в пам'яті або базі даних).
* Клієнтська програма зберігає токени в куках і надсилає їх при кожному наступному запиті.
* Сервер отримує кожен запит, що вимагає аутентифікації, за допомогою токена аутентифікує користувача та повертає запитані дані клієнтської програми.
* Коли користувач виходить, клієнтська програма видаляє його токен, тому всі наступні запити від цього клієнта стають неавтентифікованими.

[![https://hsto.org/r/w1560/webt/a5/cz/ws/a5czwswt6yvdhan0cm193d4liqq.png](https://camo.githubusercontent.com/fba8d7018605940c9de59e19e2c0557c9527177a116c8d7023e92fc6630c59c0/68747470733a2f2f6873746f2e6f72672f722f77313536302f776562742f61352f637a2f77732f6135637a777377743679766468616e30636d31393364346c6971712e706e67)](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://camo.githubusercontent.com/fba8d7018605940c9de59e19e2c0557c9527177a116c8d7023e92fc6630c59c0/68747470733a2f2f6873746f2e6f72672f722f77313536302f776562742f61352f637a2f77732f6135637a777377743679766468616e30636d31393364346c6971712e706e67)

Цей метод має кілька недоліків:

* При кожній автентифікації користувача сервер повинен створювати запис. Зазвичай вона зберігається в пам'яті, і за великої кількості користувачів є ймовірність надто високого навантаження на сервер.
* Оскільки сесії зберігаються у пам'яті, масштабувати не так просто. Якщо ви багаторазово реплікуєте сервер, то на всі нові сервери доведеться реплікувати і всі сесії користувача. Це ускладнює масштабування. (Я вважав, що цього можна уникнути, якщо мати виділений сервер для управління сесіями, але це складно реалізувати, та й не завжди можливо.)

**Аутентифікація на основі токенів**

Аутентифікація на основі токенів в останні роки стала дуже популярна через поширення односторінкових додатків, веб-API та інтернет речей. Найчастіше як токени використовуються Json Web Tokens (JWT). Хоча реалізації бувають різні, але токени JWT перетворилися на стандарт де-факто.

Під час аутентифікації на основі токенів стану не відстежуються. Ми не будемо зберігати інформацію про користувача на сервері або сесії і навіть не будемо зберігати JWT, використані для клієнтів.

Процедура аутентифікації на основі токенів:

* Користувач вводить ім'я та пароль.
* Сервер перевіряє їх і повертає токен (JWT), який може містити метадані на зразок user\_id, дозволів і т.д.
* Токен зберігається на стороні клієнта, найчастіше в локальному сховищі, але може лежати і в сховищі сесій або кук.
* Наступні запити до сервера зазвичай містять цей токен як додатковий заголовок авторизації у вигляді Bearer {JWT}. Ще токен може пересилатися в тілі запиту POST і навіть як параметр запиту.
* Сервер розшифровує JWT, якщо токен вірний, сервер обробляє запит.
* Коли користувач виходить із системи, токен на стороні клієнта знищується, з сервером взаємодіяти не потрібно.

[![https://hsto.org/r/w1560/webt/mu/rw/kv/murwkv\_rxhbsjxkogdetqbwl-hk.png](https://camo.githubusercontent.com/00c46041c6b212ae2ccd65ee4bacad4cb47e9a3050224db8654c89d7ecb691c4/68747470733a2f2f6873746f2e6f72672f722f77313536302f776562742f6d752f72772f6b762f6d7572776b765f72786862736a786b6f676465747162776c2d686b2e706e67)](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://camo.githubusercontent.com/00c46041c6b212ae2ccd65ee4bacad4cb47e9a3050224db8654c89d7ecb691c4/68747470733a2f2f6873746f2e6f72672f722f77313536302f776562742f6d752f72772f6b762f6d7572776b765f72786862736a786b6f676465747162776c2d686b2e706e67)

Метод має ряд переваг:

* Головна перевага: оскільки метод ніяк не оперує станами, серверу не потрібно зберігати записи з токенами або сесіями. Кожен токен самодостатній, містить всі необхідні для перевірки дані, а також передає затребувану інформацію користувача. Тому токени не ускладнюють масштабування.
* У куках ви просто зберігаєте ID сесій, а JWT дозволяє зберігати метадані будь-якого типу, якщо це коректний JSON.
* При використанні кук бекенд повинен виконувати пошук за традиційною SQL-базою або NoSQL-альтернативою, і обмін даними, напевно, триває довше, ніж розшифровка токена. Крім того, якщо ви можете зберігати всередині JWT додаткові дані на кшталт користувацьких дозволів, то можете заощадити і додаткові звернення пошукові запити на отримання та обробку даних.
* Припустимо, у вас є API-ресурс /api/orders, який повертає останні створені додатком замовлення, але їх можуть переглядати тільки користувачі категорії адмінів. Якщо ви використовуєте куки, то, зробивши запит, ви генеруєте одне звернення до бази даних для перевірки сесії, ще одне звернення - для отримання даних і перевірки, чи належить користувач до адмінів, і третє звернення - для отримання даних.
* А якщо ви застосовуєте JWT, то можете зберігати категорію користувача вже в токені. Коли сервер запросить його та розшифрує, ви можете зробити одне звернення до бази даних, щоб отримати потрібні замовлення.
* У використання кук на мобільних платформах є багато обмежень та особливостей. А токени дуже простіше продати на iOS і Android. До того ж, токени простіше реалізувати для додатків і сервісів інтернету речей, в яких не передбачено зберігання кук.

Завдяки цьому аутентифікація на основі токенів сьогодні набирає популярності.

**Безпарольна автентифікація**

Першою реакцією на термін «безпарольна автентифікація» може бути «Як когось аутентифікувати без пароля? Хіба таке можливе?». У наші голови впроваджено переконання, що паролі є абсолютним джерелом захисту наших акаунтів. Але якщо вивчити питання глибше, то з'ясується, що безпарольна автентифікація може бути не просто безпечною, а й безпечнішою за традиційний вход на ім'я та пароль. Можливо, ви навіть чули, що паролі застаріли.

Безпарольна аутентифікація - це спосіб конфігурування процедури входу та аутентифікації користувачів без паролів. Ідея така: замість введення пошти/імені та пароля користувачі вводять лише свою пошту. Ваша програма відправляє на цю адресу одноразове посилання, користувач по ній кликає і автоматично входить на ваш сайт/додаток. При безпарольній автентифікації додаток вважає, що до вашої скриньки надійшов лист із посиланням, якщо ви написали свою, а не чужу адресу.

Є схожий метод, при якому замість одноразового посилання SMS відправляється код або одноразовий пароль. Код або одноразовий пароль також можна надсилати поштою.

І ще один, менш (поки що) популярний (і доступний тільки на пристроях Apple) метод безпарольної аутентифікації: використовувати Touch ID для аутентифікації за відбитками пальців.

Що може піти не так: якщо хтось отримає доступ до пошт користувача, він отримає і доступ до додатків і сайтів. Але це не ваш головний біль - турбуватися про безпеку поштових акаунтів користувачів. Крім того, якщо хтось отримає доступ до чужої пошти, то зможе перехопити облікові записи в додатках з безпарольною автентифікацією, скориставшись функцією відновлення пароля. Але ми нічого не можемо вдіяти з поштою наших користувачів. Ходімо далі.

У чому переваги: ​​як часто ви користуєтеся посиланням «забули пароль» для скидання чортового пароля, який так і не змогли згадати після кількох невдалих спроб входу на сайт/додаток? Усі ми буваємо у такій ситуації. Всі паролі не згадаєш, особливо якщо ви дбаєте про безпеку і для кожного сайту робите окремий пароль (дотримуючись всіх цих «повинен складатися не менше ніж з восьми символів, містити хоча б одну цифру, малий літер і спеціальний символ»). Від цього вас позбавить безпарольна автентифікація. Знаю, ви думаєте зараз: "Я використовую менеджер паролів, ідіот". Поважаю. Але не забувайте, що переважна більшість користувачів не такі технології, як ви. Це потрібно враховувати.

**Єдина точка входу (Single Sign On, SSO)**

Звертали увагу, що коли логінишся в браузері в якомусь Google-сервісі, наприклад Gmail, а потім йдеш на Youtube або інший Google-сервіс, там не доводиться логінитися? Ти автоматично отримуєш доступ до всіх сервісів компанії. Вражає, правда? Адже хоча Gmail і Youtube - це сервіси Google, але все ж таки роздільні продукти. Як вони автентифікують користувача у всіх продуктах після єдиного входу? Цей метод називається єдиною точкою входу (Single Sign On, SSO).

Реалізувати його можна по-різному. Наприклад, використовувати центральний сервіс для оркестрації єдиного входу між кількома клієнтами. У випадку з Google цей сервіс називається Google Accounts. Коли користувач логіниться, Google Accounts створює куку, яка зберігається за користувачем, коли той ходить по сервісах, що належать компанії. Як це працює:

* Користувач входить до одного із сервісів Google.
* Користувач отримує генеровану в Google Accounts куку.
* Користувач йде до іншого продукту Google.
* Користувач знову перенаправляється в Google Accounts.
* Google Accounts бачить, що користувачеві вже присвоєно кука, і перенаправляє користувача на запитаний продукт.

Дуже простий опис єдиної точки входу: користувач входить один раз і отримує доступ до всіх систем без необхідності входити до кожної з них. У цій процедурі використовують три сутності, які довіряють другові прямо і побічно. Користувач вводить пароль (або аутентифікується інакше) у постачальника ідентифікаційної інформації (identity provider, IDP), щоб отримати доступ до постачальника послуги (service provider (SP). Користувач довіряє IDP, і SP довіряє IDP, так що SP може довіряти користувачу. просто, але конкретні реалізації бувають дуже складними.Докладніше [про цей метод аутентифікації](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://auth0.com/blog/what-is-and-how-does-single-sign-on-work/) .

**Аутентифікація в соціальних мережах (Social sign-in)** або соціальний логін (Social Login)

Ви можете аутентифікувати користувачів по облікових записах в соцмережах. Тоді користувачам не доведеться реєструватися окремо у вашому додатку.

Формально соціальний логін - це окремий метод аутентифікації. Це різновид єдиної точки входу зі спрощенням процесу реєстрації/входу користувача до вашої програми.

Найкраще з двох світів: користувачі можуть увійти у вашу програму одним кліком, якщо у них є обліковий запис в одній із соцмереж. Їм не потрібно пам'ятати логіни та паролі. Це сильно покращує досвід використання вашої програми. Вам не потрібно хвилюватися про безпеку даних і думати про перевірку адрес пошти - вони вже перевірені соцмережами. Крім того, у соцмережах вже є механізми відновлення паролю.

Як використовувати: більшість соцмереж як механізм аутентифікації використовують авторизацію через OAuth2 (деякі використовують OAuth1, наприклад Twitter). Розберемося, що таке OAuth. Соцмережа - це сервер ресурсів, ваш додаток - клієнт, а користувач, що намагається увійти у ваш додаток, - власник ресурсу. Ресурсом називається профіль користувача / інформація для аутентифікації. Коли користувач хоче увійти у вашу програму, він перенаправляє користувача в соцмережу для аутентифікації (зазвичай це спливаюче вікно з URL соцмережі). Після успішної аутентифікації користувач повинен надати вашому додатку дозвіл на доступ до свого профілю із соцмережі. Потім соцмережа повертає користувача назад у вашу програму, але вже з токеном доступу. Наступного разу програма візьме цей токен і запросить у соцмережі інформацію з профілю користувача. Так працює OAuth (заради простоти я опустив технічні подробиці).

Для реалізації такого механізму вам може знадобитися зареєструвати свою програму в різних соцмережах. Вам дадуть app\_id та інші ключі для конфігурування підключення до соціальних мереж. Також є кілька популярних бібліотек/пакетів (на зразок Passport, Laravel Socialite і т. д.), які допоможуть спростити процедуру і позбавлять зайвої метушні.

**Двофакторна аутентифікація (2FA)**

Двофакторна аутентифікація (2FA) покращує безпеку доступу за рахунок використання двох методів (також званих факторами) перевірки особистості користувача. Це різновид [багатофакторної аутентифікації](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://ru.wikipedia.org/wiki/%25D0%259C%25D0%25BD%25D0%25BE%25D0%25B3%25D0%25BE%25D1%2584%25D0%25B0%25D0%25BA%25D1%2582%25D0%25BE%25D1%2580%25D0%25BD%25D0%25B0%25D1%258F_%25D0%25B0%25D1%2583%25D1%2582%25D0%25B5%25D0%25BD%25D1%2582%25D0%25B8%25D1%2584%25D0%25B8%25D0%25BA%25D0%25B0%25D1%2586%25D0%25B8%25D1%258F) . Напевно, вам не спадало на думку, але в банкоматах ви проходите двофакторну автентифікацію: на вашій банківській картці має бути записана правильна інформація, і на додаток до цього ви вводите PIN. Якщо хтось вкраде вашу карту, то без коду він не зможе нею скористатися. (Не факт! - Прим. пер.) Тобто в системі двофакторної автентифікації користувач отримує доступ тільки після того, як надасть декілька окремих частин інформації.

Інший знайомий приклад - двофакторна автентифікація Mail.Ru, Google, Facebook і т.д. Якщо включений цей метод входу, то спочатку вам потрібно ввести логін та пароль, а потім одноразовий пароль (код перевірки), що надсилається SMS. Якщо ваш звичайний пароль був скомпрометований, обліковий запис залишиться захищеним, тому що на другому кроці входу зловмисник не зможе ввести потрібний код перевірки.

Замість одноразового пароля як другий фактор можуть використовуватися відбитки пальців або знімок сітківки.

При двофакторній аутентифікації користувач повинен надати **два з трьох** :

* **Те, що ви знаєте** : пароль або PIN.
* **Те, що у вас є** : фізичний пристрій (смартфон) або програма, що генерує одноразові паролі.
* **Частина вас** : біологічно унікальна властивість на зразок ваших відбитків пальців, голосу або знімку сітківки.

Більшість хакерів полюють на паролі та PIN-коди. Набагато важче отримати доступ до генератора токенів чи біологічних властивостей, тому сьогодні двофакторка забезпечує високу безпеку облікових записів.

Тобто, це універсальне рішення? [Можливо](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://medium.com/@the_economist/where-are-the-flaws-in-two-factor-authentication-5f7a468f41a9) , [ні](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://www.theverge.com/2017/7/10/15946642/two-factor-authentication-online-security-mess) .

І все ж таки двофакторка допоможе посилити безпеку аутентифікації у вашому додатку. Як продати? Можливо, варто не велосипедити, а скористатися існуючими рішеннями на зразок Auth0 чи Duo.

Джерела:

* [Ідентифікація, автентифікація та авторизація – у чому різниця?](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://www.kaspersky.ru/blog/identification-authentication-authorization-difference/29123/)
* [HTTP authentication](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication)
* [Authentication and Authorization Defined: What's the Difference?](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://www.loginradius.com/blog/start-with-identity/authentication-vs-authorization-infographic/)
* [Як ти реалізуєш автентифікацію, друже?](https://translate.google.com/website?sl=auto\&tl=uk\&hl=uk\&u=https://habr.com/ru/company/vk/blog/343288/)
