Сьогодні, в світі соціальних медіа, кожен з нас використовує десятки додатків і сайтів щодня. Oauth 2.0 покликаний спростити процес авторизації і, як наслідок, зробити життя користувачів простішим і безпечнішим. Виникає питання – яким чином?
Oauth 2.0 – що це таке?
Візьмемо звичайну ситуацію: ви відкриваєте який-небудь сайт, вибираєте, який провайдер даних і який конкретно обліковий запис використовувати, даєте дозвіл на використання даних (якщо необхідно) і працюєте далі від імені власника цього облікового запису. Ви не згадуєте пароль, не витрачаєте час на втомливу реєстрацію - все це зводиться до кількох кліків.
Природно, для цього у вас повинен бути обліковий запис у обраного провайдера.
Термін «провайдер» передбачає сервіс, який володіє даними користувача і, з дозволу користувача, надає стороннім сервісам (клієнтам) безпечний доступ до цих даних. Додаток, який бажає отримати дані користувача – це клієнт.
Для прикладу взята форма логіна/реєстрації на Aliexpress. В даному випадку на формі присутній вибір з кількох провайдерів - Google, Facebook, Вконтакте і Twitter.
Ви натиснете «увійти через Facebook» або «увійти через Google», Вас перенаправляють на сторінку вибору облікового запису, Ви вибираєте свій обліковий запис і все - Ви вже залогінилися.
Специфікація OAuth 2.0 визначає протокол делегування, який надає клієнтам безпечний доступ до ресурсів користувача на сервісі-провайдері. Такий підхід позбавляє користувача від необхідності вводити пароль за межами сервісу-провайдера: весь процес зводиться до натискання кнопки «Згоден надати доступ до ... ». Ідея в тому, що маючи один добре захищений аккаунт, користувач може використовувати його для аутентифікації на інших сервісах, не розкриваючи при цьому свого пароля.
На відміну від OpenID, OAuth 2.0 може використовуватися і для авторизації. Тобто, дозволяє видати права на дії, які сам сервіс-клієнт зможе виробляти від особи власника акаунту. При цьому сам власник після авторизації може взагалі не брати участь в процесі виконання дій, наприклад, сервіс з продажу квитків самостійно створює захід в календарі користувача, або гра розміщує на стіні в Facebook звіт про черговий захід.
Загальна схема OAuth 2.0 :
- Клієнт робить запит на авторизацію у власника ресурсу.
- Клієнт отримує дозвіл на авторизацію.
- Клієнт запитує токен доступу шляхом перевірки особи за допомогою сервера авторизації та забезпечення надання авторизації.
- Сервер авторизації варифікує клієнта, перевіряючи грант авторизації і, якщо він дійсний, видає токен доступу (access token) і рефреш токен (refresh token).
- Клієнт запитує захищений ресурс у провайдера і аутентифікується, надаючи токен доступу.
- Провайдер перевіряє токен доступу і, якщо він дійсний, обслуговує запит.
Отже, ми бачимо, що кінцева мета - це отримати access і refresh токени. Далі клієнт взаємодіє з провайдером даних, поки у access токена не закінчиться термін придатності. Потім, щоб отримати доступ до даних провайдера знову, клієнту потрібно скористатися refresh токеном і надіслати запит на генерацію нової пари access/refresh токенів.
Навіщо взагалі потрібен refresh токен?
Уявімо ситуацію, коли хтось заволодів Вашим access токеном і отримав доступ до захищених даних. Саме тому у токенів є термін придатності. У access токена він зазвичай маленький - від кількох секунд до кількох днів, у refresh токена - побільше. Так ось доступ до даних у зловмисника буде доти, доки не завершиться термін дії токену. Припустимо, цей хтось заволодів ще й refresh токеном і скористався ним раніше, ніж ви, тим самим отримавши новий access токен. У такому разі Ви не можете отримати дані з провайдера, але для розв'язання цієї проблеми Вам буде достатньо розлогінитися і залогінитися заново - і все! Усі старі токени стануть недійсними або видалятимуться (залежить від реалізації). Після цієї процедури Ви отримуєте нові access/refresh токени і можете спокійно продовжити роботу, а поганець, зі старими токенами, залишиться у програші.
Переваги та недоліки OAuth 2.0
З плюсів OAuth 2.0 протоколу можна виділити такі:
- Звернення до ресурсів відбувається по HTTP/HTTPS із зазначенням токена в заголовках. Це дає змогу використовувати OAuth практично в будь-яких рішеннях: мобільних і десктоп-додатках, сайтах, і навіть у плагінах для браузерів.
- Можливість авторизації користувача.
- Популярність - більшість компаній використовують його у своїх API.
- Простота реалізації та велика кількість «літератури».
- Наявність готових рішень, які можна змінювати під свої потреби.
З мінусів:
- Немає єдиного встановленого формату, внаслідок чого на кожен сервіс потрібно мати окрему реалізацію.
- Під час аутентифікації іноді доводиться робити додаткові запити для отримання навіть мінімальної інформації про користувача. Вирішується використанням jwt токена, але далеко не всі сервіси його підтримують.
- У разі крадіжки токена у зловмисника на якийсь час з'являється доступ до захищених даних. Для мінімізації цього варіанту можна використовувати токен із підписом.
Реалізацію підходу OAuth 2.0 у php можна знайти в кількох популярних пакетах послуг на GitHub:
Декілька слів про JWT
JSON Web Token - відкритий стандарт для створення токена в json форматі. Такий токен складається з трьох частин, розділених крапками: заголовок (header), набір полів (payload) і підпис. Перші два блоки представлені в json-форматі та додатково закодовані. Для заголовка є один обов'язковий ключ — alg, що вказує алгоритм підпису. Набір полів payload містить довільні пари ключ/значення. Також існують необов'язкові зарезервовані ключі (ознайомитися).
Підпис може бути згенерований як за допомогою симетричних алгоритмів шифрування, так і асиметричних. Більш того, існує окремий стандарт, який описує формат зашифрованого JWT-токену.
Приклад
У нас є певний ключ SECRET_KEY, його знає тільки сервер і додаток - клієнт (отримує його під час встановлення).
$SECRET_KEY="stFalcon";$header='{"typ":"JWT","alg":"HS256"}';$payload='{"sub":"1234567890","name":"alex","admin":true}';$unsignedToken= \sprintf("%s.%s",base64_encode($header),base64_encode($payload));$signature=hash_hmac('sha256',$unsignedToken,$SECRET_KEY);</p></ol> $tokenEncoded= \sprintf("%s.%s.%s",base64_encode($header),base64_encode($payload),base64_encode($signature));
В результаті маємо готовий токен -
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ImFsZXgiLCJhZG1pbiI6dHJ1ZX0=.MTI5MGZmYTkwMGM2YmE0ODIzNGQ2ZGI4OGYxZTM2NGY5Y2VhYzExN2NiZGNjODA0YmNhN2NhNmM1ZWUzMDQ3NA==
Теперь перевіримо токен на валідність -
$tokenDecodedArr=explode('.',$tokenEncoded); $externalHeader=$tokenDecodedArr[0];$externalPayload=$tokenDecodedArr[1];$externalSignature=$tokenDecodedArr[2]; if(base64_decode($externalSignature)===hash_hmac('sha256', \sprintf("%s.%s",$externalHeader,$externalPayload),$SECRET_KEY)){echo'matched';}else{echo'don’t mathe';}
Таким чином ми перевіряємо збігаються підписи, якщо так - JWT валідний, тобто прийшов від перевіреного джерела. Якщо підписи не збігаються, значить щось пішло не так - можливо, це ознака потенційної атаки.
В результаті використовуючи jwt ми отримуємо додатковий ступінь захисту від крадіжки своїх даних, і можливість передавати певний набір інформації без додаткових запитів.
Висновок
Підведемо підсумок. OAuth 2.0 - це простий протокол авторизації, заснований на HTTP, що дає можливість застосовувати його практично на будь-якій платформі. Він має хорошу документацію, і більшість великих майданчиків його підтримують. Таким чином, якщо ви вирішили використовувати цей протокол в своєму проєкті - це хороший вибір.