Базове розуміння Oauth 2.0

Базовое понимание Oauth 2.0

Сьогодні, в світі соціальних медіа, кожен з нас використовує десятки додатків і сайтів щодня. Oauth 2.0 покликаний спростити процес авторизації і, як наслідок, зробити життя користувачів простішим і безпечнішим. Виникає питання – яким чином?

Oauth 2.0 – що це таке?

Візьмемо звичайну ситуацію: ви відкриваєте який-небудь сайт, вибираєте, який провайдер даних і який конкретно обліковий запис використовувати, даєте дозвіл на використання даних (якщо необхідно) і працюєте далі від імені власника цього облікового запису. Ви не згадуєте пароль, не витрачаєте час на втомливу реєстрацію - все це зводиться до кількох кліків.

Природно, для цього у вас повинен бути обліковий запис у обраного провайдера.

Термін «провайдер» передбачає сервіс, який володіє даними користувача і, з дозволу користувача, надає стороннім сервісам (клієнтам) безпечний доступ до цих даних. Додаток, який бажає отримати дані користувача – це клієнт.

Для прикладу взята форма логіна/реєстрації на Aliexpress. В даному випадку на формі присутній вибір з кількох провайдерів - Google, Facebook, Вконтакте і Twitter.

Ви натиснете «увійти через Facebook» або «увійти через Google», Вас перенаправляють на сторінку вибору облікового запису, Ви вибираєте свій обліковий запис і все - Ви вже залогінилися.

Специфікація OAuth 2.0 визначає протокол делегування, який надає клієнтам безпечний доступ до ресурсів користувача на сервісі-провайдері. Такий підхід позбавляє користувача від необхідності вводити пароль за межами сервісу-провайдера: весь процес зводиться до натискання кнопки «Згоден надати доступ до ... ». Ідея в тому, що маючи один добре захищений аккаунт, користувач може використовувати його для аутентифікації на інших сервісах, не розкриваючи при цьому свого пароля.

На відміну від OpenID, OAuth 2.0 може використовуватися і для авторизації. Тобто, дозволяє видати права на дії, які сам сервіс-клієнт зможе виробляти від особи власника акаунту. При цьому сам власник після авторизації може взагалі не брати участь в процесі виконання дій, наприклад, сервіс з продажу квитків самостійно створює захід в календарі користувача, або гра розміщує на стіні в Facebook звіт про черговий захід.

Загальна схема OAuth 2.0 :

  1. Клієнт робить запит на авторизацію у власника ресурсу.
  2. Клієнт отримує дозвіл на авторизацію.
  3. Клієнт запитує токен доступу шляхом перевірки особи за допомогою сервера авторизації та забезпечення надання авторизації.
  4. Сервер авторизації варифікує клієнта, перевіряючи грант авторизації і, якщо він дійсний, видає токен доступу (access token) і рефреш токен (refresh token).
  5. Клієнт запитує захищений ресурс у провайдера і аутентифікується, надаючи токен доступу.
  6. Провайдер перевіряє токен доступу і, якщо він дійсний, обслуговує запит.

Отже, ми бачимо, що кінцева мета - це отримати 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, що дає можливість застосовувати його практично на будь-якій платформі. Він має хорошу документацію, і більшість великих майданчиків його підтримують. Таким чином, якщо ви вирішили використовувати цей протокол в своєму проєкті - це хороший вибір.