Разберете как наистина работят най-широко използваните протоколи за удостоверяване и оторизация

Всички сме виждали бутоните „влизане с Google“ и „свързване с Facebook“ на уебсайтове и мобилни приложения. Щракнете върху бутона и се отваря екран, който казва: „Това приложение иска достъп до вашия обществен профил, контакти…“ и ви пита дали искате да предоставите достъп. Това е OAuth на високо ниво. Разбирането на тези протоколи е от решаващо значение за всеки софтуерен инженер, експерт по сигурността и дори хакер.

TL;DR

Пълно ръководство за OAuth 2.0 и OpenID Connect, двата най-широко използвани протокола в интернет днес за оторизация и удостоверяване. OAuth 2.0 се използва за оторизация и OpenID Connect се използва за удостоверяване. Има два най-често срещани потока за оторизация на OAuth 2.0, поток от код за оторизация за приложения от страна на сървъра и имплицитен поток за приложения, базирани на браузър. OpenID Connect е слой за идентичност върху протокола OAuth 2.0, за да направи OAuth подходящ за случаи на използване на удостоверяване.

Защо OAuth?

За да разберем причината за раждането на OAuth, трябва да разберем термин, наречен Делегирана авторизация.

Делегирано упълномощаване

Делегираната авторизация е подход за разрешаване на достъп на приложение на трета страна до данните на потребителя.

Два подхода за делегирана оторизация

Има два подхода за делегирано упълномощаване, дали давате на приложението на трета страна паролата за вашия акаунт, така че те да могат да влизат в акаунта ви от ваше име и да имат достъп до вашите данни или давате на приложението достъп до вашите данни чрез OAuth, без да давате паролата си (и никой от нас няма да даде паролата си!).

След като знаем необходимостта и важността на OAuth, нека се потопим по-дълбоко в протокола.

Какво е OAuth?

OAuth (Open Authorization) е стандартен протокол за делегирана авторизация. Той позволява на приложенията да имат достъп до потребителски данни без паролата на потребителя.

OAuth 2.0 терминология

Разбирането на този протокол изисква да разберем неговата терминология:

  • Собственик на ресурс: Потребителят, който притежава данните, до които клиентското приложение иска да има достъп.
  • Клиент: Приложението, което иска достъп до данните на потребителя.
  • Сървър за оторизация: Сървърът за оторизация упълномощава клиента за достъп до данните на потребителя, като предоставя разрешение от потребителя.
  • Сървър за ресурси: Системата, която съхранява данните, до които клиентът иска да има достъп. В някои случаи сървърът за ресурси и сървърът за оторизация са едни и същи.
  • Означение за достъп: Означението за достъп е единственият ключ, който клиентът може да използва за достъп до предоставените данни от потребителя на сървъра за ресурси.

Разгледайте тази терминология в абстрактния поток на OAuth 2.0:

Ключът/разрешението за оторизация може да бъде от тип код или токен. По-късно ще научим за различните разрешения. Сега нека да разгледаме подробно процеса на оторизация:

  1. Потребителят стартира процеса на оторизация, обикновено чрез щракване върху бутон като Свързване с Google или Facebook или друга услуга.
  2. След това клиентът пренасочва потребителя към сървъра за оторизация. При пренасочване клиентът изпраща информация като идентификатор на клиента и URI адрес за пренасочване.
  3. Сървърът за оторизация обработва удостоверяването на потребителя и показва екран за съгласие, предоставяйки разрешение от потребителя. Ако влизате с Google, трябва да предоставите идентификационните си данни за вход на Google — т.е. accounts.google.com, а не на клиента.
  4. Ако потребителят предостави разрешение, сървърът за оторизация пренасочва потребителя към клиента с ключа за оторизация (код/токен).
  5. След това клиентът изисква ресурсния сървър с включен ключ за оторизация, като иска от ресурсния сървър да отговори с данните на потребителя.
  6. След това ресурсният сървър валидира ключа за оторизация и отговаря с исканите данни на клиента.

Ето как потребителите дават на приложения на трети страни достъп до данните си, без да им дават паролата. На този етап възникват следните въпроси:

  • Как да ограничим достъпа на клиента само до част от нашите данни на ресурсния сървър?
  • Ами ако искаме клиентът само да чете нашите данни и да не ги променя?

Тези въпроси ни отвеждат до друга важна част от OAuth терминологията: обхвати.

Обхвати в OAuth

Обхватите в OAuth 2.0 се използват за ограничаване на достъпа на приложението до данните на потребителя. Чрез издаване на разрешение за разрешение, което е ограничено само до обхватите, предоставени от потребителя.

Когато клиентът отправи заявка към сървъра за оторизация за предоставяне на оторизация, той изпраща списък с обхвати с него. Сървърът за оторизация използва този списък с обхвати, за да генерира екран за съгласие и предоставя разрешение от потребителя. Ако потребителят се съгласи с екрана за съгласие, сървърът за оторизация издава токен или код за оторизация, който е ограничен само до обхватите, предоставени от потребителя.

Например, ако разреша на клиентско приложение да вижда списъка с моите контакти в Google, тогава токенът, издаден на клиента от сървъра за оторизация, не може да се използва за изтриване на моите контакти или за виждане на събитията в календара ми — обхватът му е само за четене на моя Google Контакти.

Настройка за OAuth 2.0

Преди да преминете към OAuth потоци, добре е да знаете някои предишни конфигурации на OAuth. Когато се инициира заявка за предоставяне на оторизация, клиентът изпраща някои конфигурационни данни към сървъра за оторизация като параметри на заявка. Основните параметри на заявката са:

  • response_type типа отговор, който искаме да получим от сървъра за оторизация.
  • scope списък с обхвати, до които клиентът иска достъп. Този списък се използва от сървъра за оторизация за генериране на екран за съгласие за потребителя.
  • client_id се предоставя от услугата за оторизация при настройване на клиента за OAuth. Този идентификатор помага на сървъра за оторизация да определи клиента, който инициира OAuth потока.
  • redirect_uri казва на сървъра за оторизация къде да отиде, когато OAuth потокът приключи.
  • client_secret се предоставя от услугата за оторизация. Този параметър може или не може да се изисква въз основа на OAuth потока. Ще видим важността му в потока на кода за оторизация.

Разбиране на различни OAuth потоци

Двата най-често използвани потока на OAuth 2.0 са потокът на код за оторизация за базирани на сървър приложения и имплицитният поток за чисти JavaScript приложения с една страница (SPA).

За да обясня потоците на OAuth, разглеждам Google като доставчик на OAuth услуга.

Поток на код за оторизация

Потокът на кода за оторизация или предоставянето на код за оторизация е идеален OAuth поток, който се счита за силно защитен, тъй като използва както предния канал (браузър), така и задния канал (сървър), за да внедри механизма OAuth 2.0.

Клиентът започва последователността за оторизация, като пренасочва потребителя към сървъра за оторизация с response_type, зададен на code, което казва на сървъра за оторизация да отговори с код за оторизация. URI адресът за този поток изглежда така:

https://accounts.google.com/o/oauth2/v2/auth?
 response_type=code&
 client_id=your_client_id&
 scope=profile%20contacts&
 redirect_uri=https%3A//oauth2.example.com/code

В горната заявка клиентът изисква разрешение от потребителя за достъп до публичния му профил и контакти, като ги дефинира в параметъра scope на заявката. Резултатът от тази заявка е код за оторизация, който клиентът може да обмени за токен за достъп. Кодът за оторизация изглежда така:

4/W7q7P51a-iMsCeLvIaQc6bYrgtp9

Защо да обменяте код за токен?

Токенът за достъп е единственото нещо, което може да се използва за достъп до данни на ресурсния сървър, а не кодът на приложението. Така че защо клиентът е настроен от response_type до code, когато всъщност се нуждае от токен за достъп? Причината е да се направи OAuth потокът много сигурен.

Проблем:Означението за достъп е секретна част от информацията, до която не искаме някой да има достъп. Ако клиентът поиска токен за достъп директно и го съхрани в браузъра, той може да бъде откраднат, тъй като браузърите не са напълно защитени. Всеки може да види изходния код на страницата или потенциално да използва инструменти за разработка, за да придобие токена за достъп.

Решение: За да се избегне разкриването на токена за достъп в браузъра, предният канал на клиента получава кода на приложението от сървъра за оторизация, след което изпраща кода на приложението до задния канал на клиента. Сега, за да обмените този код на приложението за токен за достъп, е необходимо нещо, наречено client_secret. client_secret се знае само от задния канал на клиента, след което задният канал прави POST заявка до сървъра за оторизация с включен код на приложение и тайна на клиента. Заявката може да изглежда така:

POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded
code=4/W7q7P51a-iMsCeLvIaQc6bYrgtp9&
client_id=your_client_id&
client_secret=your_client_secret_only_known_by_server&
redirect_uri=https%3A//oauth2.example.com/code

Сървърът за оторизация валидира тайната на клиента и кода на приложението и отговаря с токен за достъп. Задният канал съхранява токена за достъп и потенциално го използва за достъп до ресурсен сървър. По този начин браузърът няма достъп до маркера за достъп.

Имплицитен поток

Неявният поток OAuth 2.0 се използва, когато нямате бекенд канал и уебсайтът ви е статичен сайт, който използва само браузъра. В този случай пропускате последната стъпка, която се случва на обратния канал, когато обменяте кода на приложението за токен за достъп. В неявния поток сървърът за оторизация отговаря незабавно с токен за достъп.

Клиентът пренасочва браузъра към URI на сървъра за оторизация, за да започне потока оторизация с response_type, зададен на token. Сървърът за оторизация обработва влизането и съгласието на потребителя. Резултатът от заявката е токен за достъп, който клиентът може да използва за достъп до ресурсен сървър.

Неявният поток се счита за по-малко сигурен, тъй като браузърът е отговорен за управлението на токена за достъп, така че той потенциално може да бъде откраднат. Все пак той се използва широко за приложения с една страница.

Удостоверяване срещу оторизация

Както знаем, OAuth решава проблема с делегираната авторизация, но не предоставя стандартен начин за удостоверяване на потребителя. Може да се каже, че:

  • OAuth 2.0 е за оторизация.
  • OpenID Connect е за удостоверяване.

Ако сте объркани от тези термини, ето разликата между тях:

  • Удостоверяването е уверението, че комуникиращият обект е заявеният.
  • Упълномощаването е процес на проверка дали комуникиращият обект има достъп до ресурса.

С други думи, удостоверяването се интересува кой сте вие, оторизацията се интересува какви разрешения имате.

OpenID Connect

OpenID Connect е слой за идентичност върху протокола OAuth 2.0. Той разширява OAuth 2.0, за да стандартизира начин за удостоверяване.

OAuth не предоставя самоличност на потребителя веднага, а по-скоро предоставя токен за достъп за оторизация. OpenID Connect позволява на клиента да идентифицира потребителя въз основа на удостоверяването, извършено от сървъра за оторизация. Това се постига чрез дефиниране на обхват с име openid при заявка на сървъра за оторизация за потребителско влизане и съгласие. openid е задължителен обхват, за да кажете на сървъра за оторизация, че се изисква OpenID Connect.

URI за заявка за удостоверяване на OpenID Connect, направена от клиента, изглежда така:

https://accounts.google.com/o/oauth2/v2/auth?
 response_type=code&
 client_id=your_client_id&
 scope=openid%20contacts&
 redirect_uri=https%3A//oauth2.example.com/code

Резултатът от заявката е код на приложение, който клиентът може да обмени за маркер за достъп и ID маркер. Ако OAuth потокът е имплицитно, тогава сървърът за оторизация отговаря веднага с токен за достъп и токен за идентификатор.

ID токенът е JWT или JSON уеб токен. JWT е кодиран токен, който се състои от три части: заглавка, полезен товар и подпис. След като придобие ID токена, клиентът може да го декодира, за да получи информацията за потребителя, кодирана в частта за полезен товар - като това:

{
  "iss": "https://accounts.google.com",
  "sub": "10965150351106250715113082368",
  "email": "[email protected]",
  "iat": 1516239022,
  "exp": 1516242922
}

Искове

Полезният товар на ID токена съдържа някои полета, известни като претенции. Основните претенции са:

  • iss издател на токени.
  • sub уникален идентификатор за потребителя.
  • email имейл на потребителя.
  • iat времето за издаване на токен, представено като Unix време.
  • exp време на изтичане на токена, представено като Unix време.

Претенциите обаче не се ограничават до тези полета. От сървъра за оторизация зависи да кодира твърденията. Клиентът може да използва тази информация, за да удостовери потребителя.

Ако клиентът се нуждае от повече потребителска информация, клиентът може да посочи стандартни обхвати на OpenID Connect, за да каже на сървъра за оторизация да включи необходимата информация в полезния товар на ID токена. Тези обхвати са profile, email, address и phone.

Крайна бележка

Винаги е добре да практикувате това, което сте научили. За да играете с обхвати на OAuth 2.0, кодове за оторизация и токени, отидете на Google OAuth 2.0 Playground.

Благодаря, че прочетохте до края! Ако го намирате за полезен, моля, подкрепете, като аплодирате историята.