Что такое токен аккаунта
Перейти к содержимому

Что такое токен аккаунта

  • автор:

Справочник анонима. Как работают токены аутентификации и в чем их отличия от паролей

Статьи из этого цикла публикуются бесплатно и доступны всем. Мы убеждены, что каждый имеет право на базовые знания о защите своих данных.

Другие статьи цикла:

  • «Теория и практика шифрования почты»;
  • «Виды шифрования и защиты трафика, выбор софта»;
  • «Как шифровать переписку в Jabber: пошаговая инструкция»;
  • «Делаем шпионскую флешку с защищенной операционкой Tails».

Если для тебя эти материалы тривиальны — отлично! Но ты сделаешь доброе дело, отправив ссылку на них своим друзьям, знакомым и родственникам, менее подкованным в технических вопросах.

Подписываемся под данными

И людям, и программам нужно знать, что данные были созданы доверенным источником и остались неизменными. Для этого была придумана технология генерации специального хеша (подписи), который подтверждает целостность информации и достоверность ее отправителя/создателя. Для создания этой самой подписи используется схема из нескольких шагов, цель которых — защитить данные от подделки.

Схема генерации HMAC (hash-based message authentication code), кода аутентификации сообщений с использованием хеш-функции

Схема генерации HMAC (hash-based message authentication code), кода аутентификации сообщений с использованием хеш-функции

Другие статьи в выпуске:

Xakep #247. Мобильная антислежка

Алгоритм хеширования может меняться, но суть этого подхода проста и неизменна: для подтверждения целостности сообщения необходимо снова найти подпись защищаемых данных и сравнить ее с имеющейся подписью.

Придумываем коды доступа

Люди, которые придумали двухфакторную аутентификацию, по всей видимости, руководствовались принципом «одна голова хорошо, а две — лучше». И действительно — два пароля точно безопаснее одного. Но пароли, которые отправляет сайт в SMS, нельзя назвать абсолютно защищенными: сообщение чаще всего можно перехватить. Другое дело — специальные приложения для аутентификации, они нацелены на полную защиту всего процесса входа пользователя в аккаунт. Именно их мы сейчас с тобой и разберем.

Создание безопасных одноразовых паролей состоит из двух этапов:

  1. Первичная настройка — включение двухфакторной аутентификации.
  2. Использование пароля — непосредственный ввод кода и отправка для проверки.

В таком случае пользователь с помощью приложения, доступного на любом устройстве, сможет генерировать коды в соответствии со всеми стандартами.

Первоначальная настройка приложения заключается в обмене секретным ключом между сервером и приложением для аутентификации. Затем этот секретный ключ используется на устройстве клиента, чтобы подписать данные, которые известны и серверу, и клиенту. Этот ключ и служит главным подтверждением личности пользователя при вводе пароля на сервере.

На самом деле весь секрет — последовательность из случайных символов, которые закодированы в формате Base32. Суммарно они занимают не меньше 128 бит, а чаще и все 190 бит. Эту последовательность и видит пользователь как текст или QR-код.

Так выглядит код QR для обмена секретом Так выглядит код QR для обмена секретом
Тот же самый секрет, только текстом Тот же самый секрет, только текстом

Как приложение создает одноразовые коды? Все просто: приложение с помощью ключа хеширует какое-то значение, чаще всего число, берет определенную часть получившегося хеша и показывает пользователю в виде числа из шести или восьми цифр.

С самого начала для этого числа разработчики использовали простой счетчик входов. Сервер считал количество раз, которое ты заходил, например, на сайт, а приложению было известно, сколько раз ты запрашивал одноразовый пароль. Именно это значение и использовалось для создания каждого следующего одноразового кода. В современных приложениях вместо счетчика берется текущее время — и это намного удобнее для пользователя: счетчики входов часто сбивались, и их приходилось настраивать заново.

Теперь давай попробуем посчитать код для авторизации самостоятельно. Для примера представим, что мы решили прямо в Новый год опубликовать фотографию красивого фейерверка и, чтобы это сделать, нужно войти в свой аккаунт, а значит, нам не обойтись без одноразового пароля.

Возьмем время празднования Нового года в формате UNIX ( 1577811600000 ) и посчитаем порядковый номер нашего пароля: поделим на 30 секунд — 52593720 . Воспользуемся нашим секретом и вычислим хеш — по стандарту RFC 6238 это функция SHA-1:

Не забудь про аргумент -n для команды echo , чтобы в ее выводе не было ненужного перевода строки, иначе хеш будет другим.

Теперь дело за малым: нужно получить шесть цифр, которые мы и будем отправлять на сервер при авторизации. Возьмем последние четыре бита хеша — сдвиг, — это будет число a , или 10. Именно по этому сдвигу расположен наш код, который пока в виде байтов, — 03b08b12 = 61901586 . Отбросим все цифры этого числа, кроме шести последних, и получим наш новенький, готовый к использованию одноразовый код — 901586 .

Входим в приложение

Ни одно современное приложение не спрашивает пароль у пользователя постоянно, поскольку пользователей это раздражает. Именно поэтому разработчики и ученые-криптографы придумали токены, которые могут заменить собой пару логин — пароль. Перед учеными стояла задача не столько скрыть какую-то информацию, сколько создать общий стандарт для ее хранения и подтверждения ее надежности. Для всего этого была придумана технология JSON Web Token (JWT).

Как работает JWT?

Если есть данные, достоверность которых следует подтвердить, нам надо подписать их секретным ключом, используя HMAC. Для этого применяется такой же способ хеширования, что и для одноразовых паролей, только вместо шести цифр берется весь хеш целиком. Единственная разница — это сам алгоритм хеширования: в таких токенах SHA-1 считают слишком коротким и небезопасным, поэтому обычно используют SHA-256.

Главная задача JWT — подтверждение личности создателя токена и сопутствующих данных. Обычно содержимое токена — логин или другой идентификатор пользователя.

Давай попробуем создать свой токен. Продолжим нашу маленькую историю с публикацией фотографии фейерверка в соцсети: мы ввели одноразовый пароль, сервер подтвердил нашу личность и хочет выдать токен, чтобы мы смогли с его помощью открыть наше приложение.

Любой токен состоит из трех частей: заголовка со служебной информацией, данных и подписи. Так как стандартом безопасности считается SHA-256, то мы запишем его в наш заголовок.

Внутри самого токена будет храниться информация об идентификаторе аккаунта, в который мы только что вошли.

Закодируем наши данные и заголовок в Base64 и соединим их через точку. Это делается, чтобы безопасно пересылать данные через HTTP: eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjogMTIzNDU2fQ . Теперь, зная и данные, и заголовок, мы можем посчитать ее хеш, который содержит наш пароль — строку QWERTYUI12345678 .

Этот хеш нам тоже надо перевести в кодировку Base64 и затем присоединить к уже имеющейся строке из заголовка и данных: eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjogMTIzNDU2fQ.4Ka0ipYe4/x-s4r82xqO8i77BXLh1TM7hdsqpmkZ6Y4 — это и есть наш токен. Можно пользоваться!

Так выглядит наш токен

Так выглядит наш токен

Подробнее про стандарт JWT можно почитать на сайте организации RFC, а про реализацию для своего любимого языка — на сайте jwt.io.

Заключение

Теперь ты знаешь, что происходит каждый день, когда ты открываешь браузер и заходишь в какой-нибудь веб-сервис. Понимая, как это работает, ты сможешь лучше защитить свои данные, а возможно, даже решишь применить какой-то из этих методов в своих разработках.

Как узнать токен ВК и как он выглядит?

Сегодня мы попробуем разобраться, можно ли узнать токен от ВК другого пользователя. Попутно, объясним, что это за штука такая и с чем ее едят.

Забегая вперед, сразу ответим, законных способов узнать токен чужого аккаунта ВК, нет. Разве что, вынудить человека вам его сообщить, открыто или хитростью.

Что такое токен?

Токен (access_token) – это ключ или код доступа. Еще, его называют подписью, зашифрованной информацией, секретным шифром.

Не путать с логином и/или паролем, это совершенно разные вещи.

Логин и пароль – это входные данные от страницы. Token – это комбинация, разрешающая или запрещающая определенный набор действий.

Для чего нужен этот ключ? Что он открывает, подписывает и какую информацию хранит?

  1. Это ключ доступа к API методам ВК;
  2. API методы – это набор инструментов или действий, с помощью которых одна программа взаимодействует с другой;

Каждый раз, когда пользователь через вспомогательную утилиту совершает в ВК какое-то действие, сервер идентифицирует его. Это делается с целью определить круг полномочий этого приложения.

Например, пользователь авторизовывается в ВК через Kate Mobile. Если он входит на страницу, сервер понимает, хозяин это или гость. Для последнего отображается лишь часть информации, ограниченная настройками приватности. У хозяина доступ полный. То есть, и к скрытым фоткам, и к личным данным, и возможность выполнить любые настройки. Или, пользователь хочет опубликовать что-то на стене. Сервер уточняет, есть ли у данной проги доступ на это действие. Если да, позволяет сделать пост, если нет, выдает ошибку. И т.д.

Каким образом система производит идентификацию? Она считывает подпись пользователя. Тот самый токен. Представляет собой уникальную длиннющую строку из английских букв и цифр. Она содержит ФИО человека и перечень разрешенных функций.

Если кому-то удастся узнать чужой токен, он сможет заходить в ВК от имени его владельца. Соответственно, получить полный доступ к его возможностям и полномочиям.

Код может соответствовать, как пользователю, так и сообществу или приложению (например, игре какой-нибудь). Ключ доступа группы создается в ее настройках. Приложения – в настройках программы. Пользователя – складывается автоматически, когда человек авторизовывается в ВК.

Вот пример действия пользовательского токена:

  • Человек пытается зайти в какое-нибудь приложение через свой аккаунт в ВК. Например, через альтернативного клиента;
  • Просто так ВКонтакте не позволит сторонней проге работать через себя. Он формирует запрос, с целью узнать приложение получше;
  • Пользователь получает сообщение примерно такого содержания: Приложение «N» требует доступа к следующим разделам вашего аккаунта ВК: Сообщения, Стена, Список контактов, Группы;
  • Вам остается разрешить доступ или запретить. В первом случае вы сможете зайти в данную утилиту через ВК. Более того, будет сформирован ключик, и при следующем входе ничего разрешать уже не придется. Во втором, нет.

Как узнать токен?

Давайте рассмотрим, как узнать и где найти токен своей страницы ВК и своего сообщества.

Код профиля

Вы должны понимать, токен есть не у каждой страницы. Он не является аналогом логина и пароля, поэтому, как правило, мало кому нужен. Если вы еще не генерировали ни одного ключа, инструкция ниже «споткнется» на «Error».

Итак, рассмотрим, как узнать или где взять токен ВК своей страницы (не чужой):

Это делается прямо из браузера:

  • Вставьте в адресную строку следующую ссылку: https://api.vk.com/oauth­/token?grant_type=password​&client_id=2274003​&client_secret=hHbZxrka2uZ6jB1inYsH​&username= ​&password=.
  • Вместо «Username» впишите телефон, к которому привязана страница, вместо «Password» – ее пароль.
  • Кликните по Enter;
  • Комбинация после «access_token=» и до «&user_id» – и есть token_access;
  • Скопируйте его или выпишите на листок бумаги.

Ключ доступа группы

Допустим, вы являетесь админом некоего сообщества. Ранее, вы подключили к нему сервис по созданию чат-ботов. Был сформирован ключ доступа, который сейчас вы хотите посмотреть.

Где взять и как узнать токен группы ВК?

  • Зайдите в свое сообщество;
  • Кликните по клавише «Управление»;

  • Перейдите к пункту «Работа с API»;
  • Появится окно со скрытым списком ключей доступа. Возле каждого есть клавиша «Показать»;
  • Жмите. Далее, подтвердите действие (код на телефон) и комбинация станет видимой полностью.
  • Готово, теперь вы разобрались, как узнать токен группы ВК для бота. Аналогично можно посмотреть и другие подписи.

Ключ приложения

Рассмотрим, как узнать токен пользователя по id созданного им приложения в ВК:

  • Зайдите в раздел создания приложений: https://vk.com/apps?act=manage;
    Нажмите «Создать»;

  • Выберите тип «Standalone», придумайте название;

  • Сохранитесь;
  • Найдите в колонке слева пункт «Настройки»;
  • Во втором поле сверху будет отображен ключ доступа.

Чтобы включить приложение, вставьте в адресную строку браузера ссылку: https://oauth.vk.com/authorize?client_id=12345&scope=photos,audio,video,docs,notes,pages,status,offers,questions,wall,groups,email,notifications,stats,ads,offline,docs,pages,stats,notifications&response_type=token. Вместо 12345 впишите ID приложения.

После нажатия Enter выйдет окно с разрешениями, которые, в случае подтверждения, запишутся на токен.

Можно ли узнать чужой код доступа?

Итак, вас интересует, как узнать токен другого человека, например, друга в ВК. Мы уже писали вначале, это невозможно. По крайней мере, законным или официальным путем. Данные сведения считаются закрытыми и надежно охраняются системой безопасности соцсети.

Если умеете взламывать, вперед! Но вы должны понимать, что идете на правонарушение. Со всеми вытекающими. В сети можно найти уйму способов узнать токен ВК другого человека, как рабочих, так и нет. Мы против неправомерных действий, а потому, ничего тут рекомендовать не станем. Упомянули же об этом лишь для полноты картины.

Что дает знание ключа?

Мы рассказали, как узнать свой токен ВК со страницы, и пояснили, что чужие ключи недоступны. Теперь поговорим о том, что же они «открывают».

Вы получите доступ к всем разрешениям данного пользователя, сообщества или приложения.

Например, вы завладели кодами, которые были выданы приложению «Гости ВК». Ему был разрешен доступ к списку контактов, фотографиям, и, например, личным данным хозяина страницы. Значит и вы теперь сможете посмотреть его друзей, альбомы и закрытые личные данные. Все остальное станется под запретом: сообщения не напишете, настройки не поменяете, ленту новостей не почитаете.

И т.д. Чем больше полномочий давал полученный код, тем больше теперь у вас возможностей. Получается, страница остается при своем владельце, но человек, который завладел ее кодами, тоже может на ней похозяйничать. В рамках дозволенного, конечно. Например, посмотреть или включиться в чужую беседу ВК, если удалось узнать токен, получится только если у последнего есть такое разрешение.

К слову, ни один токен ни дает узнать пароль, поэтому отжать аккаунт злоумышленники никак не сумеют.

Теперь вы знаете, где в ВК найти токены. Удалить их невероятно просто: завершите все сеансы на странице или смените пароль. Удалить ключи в сообществе можно через Управление – Работа с API – Удалить.

zmts / tokens.md

Аутентификация(authentication, от греч. αὐθεντικός [authentikos] – реальный, подлинный; от αὐθέντης [authentes] – автор) — это процесс проверки учётных данных пользователя (логин/пароль). Проверка подлинности пользователя путём сравнения введённого им логина/пароля с данными сохранёнными в базе данных.

Авторизация(authorization — разрешение, уполномочивание) — это проверка прав пользователя на доступ к определенным ресурсам.

Например, после аутентификации юзер sasha получает право обращаться и получать от ресурса «super.com/vip» некие данные. Во время обращения юзера sasha к ресурсу vip система авторизации проверит имеет ли право юзер обращаться к этому ресурсу (проще говоря переходить по неким разрешенным ссылкам)

  1. Юзер c емайлом sasha_gmail.com успешно прошел аутентификацию
  2. Сервер посмотрел в БД какая роль у юзера
  3. Сервер сгенерил юзеру токен с указанной ролью
  4. Юзер заходит на некий ресурс используя полученный токен
  5. Сервер смотрит на права(роль) юзера в токене и соответственно пропускает или отсекает запрос

Собственно п.5 и есть процесс авторизации.

Дабы не путаться с понятиями Authentication/Authorization можно использовать псевдонимы checkPassword/checkAccess(я так сделал в своей API)

JSON Web Token (JWT) — содержит три блока, разделенных точками: заголовок(header), набор полей (payload) и сигнатуру. Первые два блока представлены в JSON-формате и дополнительно закодированы в формат base64. Набор полей содержит произвольные пары имя/значения, притом стандарт JWT определяет несколько зарезервированных имен (iss, aud, exp и другие). Сигнатура может генерироваться при помощи и симметричных алгоритмов шифрования, и асимметричных. Кроме того, существует отдельный стандарт, отписывающий формат зашифрованного JWT-токена.

Пример подписанного JWT токена (после декодирования 1 и 2 блоков):

Токены предоставляют собой средство авторизации для каждого запроса от клиента к серверу. Токены(и соответственно сигнатура токена) генерируются на сервере основываясь на секретном ключе(который хранится на сервере) и payload’e. Токен в итоге хранится на клиенте и используется при необходимости авторизации какого-либо запроса. Такое решение отлично подходит при разработке SPA.

При попытке хакером подменить данные в header’ре или payload’е, токен станет не валидным, поскольку сигнатура не будет соответствовать изначальным значениям. А возможность сгенерировать новую сигнатуру у хакера отсутствует, поскольку секретный ключ для зашифровки лежит на сервере.

access token — используется для авторизации запросов и хранения дополнительной информации о пользователе (аля user_id, user_role или еще что либо, эту информацию также называет payload). Все поля в payload это свободный набор полей необходимый для реализации вашей частной бизнес логики. То бишь user_id и user_role не являются требованием и представляют собой исключительно частный случай. Сам токен храним не в localStorage как это обычно делают, а в памяти клиентского приложения.

refresh token — выдается сервером по результам успешной аутентификации и используется для получения новой пары access/refresh токенов. Храним исключительно в httpOnly куке.

Каждый токен имеет свой срок жизни, например access: 30 мин, refresh: 60 дней

Поскольку токены(а данном случае access) это не зашифрованная информация крайне не рекомендуется хранить в них какую либо sensitive data (passwords, payment credentials, etc. )

Роль рефреш токенов и зачем их хранить в БД. Рефреш на сервере хранится для учета доступа и инвалидации краденых токенов. Таким образом сервер наверняка знает о клиентах которым стоит доверять(кому позволено авторизоваться). Если не хранить рефреш токен в БД то велика вероятность того что токены будут бесконтрольно гулять по рукам злоумышленников. Для отслеживания которых нам придется заводить черный список и периодически чистить его от просроченных. В место этого мы храним лимитированный список белых токенов для каждого юзера отдельно и в случае кражи у нас уже есть механизм противодействия(описано ниже).

Как ставить куки ?

Для того что бы refreshToken кука была успешно уставленна и отправлена браузером, адреса эндпоинтов аутентификации( /api/auth/login , /api/auth/refresh-tokens , /api/auth/logout ) должны располагася в доменном пространстве сайта. Тоесть для домена super.com на сервере ставим куку с такими опциями:

Таким образом кука установится в браузер и прийдет на все эндпоинты по адресу super.com/api/auth/<any-path>

Если у нас монолит и за аутентификацию отвечает один и тот-же API, тут проблем не должно быть. Но если за аутентификацию отвечает отдельный микросервис, прячем его средствами nginx по выше указанному пути ( super.com/api/auth ).

Логин, создание сессии/токенов (api/auth/login):

  1. Пользователь логинится в приложении, передавая логин/пароль и fingerprint браузера (ну или некий иной уникальный идентификатор устройства если это не браузер)
  2. Сервер проверят подлинность логина/пароля
  3. В случае удачи создает и записывает сессию в БД < userId: uuid, refreshToken: uuid, expiresIn: int, fingerprint: string, . >(схема таблицы ниже)
  4. Создает access token
  5. Отправляет клиенту access и refresh token uuid (взятый из выше созданной сессии)
  1. Клиент сохраняет токены(access в памяти приложения, refresh сетится как кука автоматом)

На что нужно обратить внимание при установке refresh куки:

  • maxAge куки ставим равную expiresIn из выше созданной сессии
  • В path ставим корневой роут auth контроллера ( /api/auth ) это важно, таким образом токен получат только те хендлеры которым он нужен( /api/auth/logout и /api/auth/rerfesh-tokens ), остальные обойдутся(нечего зря почём отправлять sensitive data).

Стоит заметить, что процесс добавления сессии в таблицу должен имеет свои меры безопасности. При добавлении стоит проверять сколько рефреш-сессий всего есть у юзера и, если их слишком много или юзер конектится одновременно из нескольких подсетей, стоит предпринять меры. Имплементируя данную проверку, я проверяю только что бы юзер имел максимум до 5 одновременных рефреш-сессий максимум, и при попытке установить следующую удаляю предыдущие. Все остальные проверки на ваше усмотрение в зависимости от задачи.

Таким образом если юзер залогинился на пяти устройствах, рефреш токены будут постоянно обновляться и все счастливы. Но если с аккаунтом юзера начнут производить подозрительные действия(попытаются залогинится более чем на 5’ти устройствах) система сбросит все сессии(рефреш токены) кроме последней.

Перед каждым запросом клиент предварительно проверяет время жизни access token’а (да берем expiresIn прямо из JWT в клиентском приложении) и если оно истекло шлет запрос на обновление токенов. Для большей уверенности можем обновлять токены на несколько секунд раньше. То есть кейс когда API получит истекший access токен практически исключен.

Что такое fingerprint ? Это инструмент отслеживания браузера вне зависимости от желания пользователя быть идентифицированным. Это хеш сгенерированный js’ом на базе неких уникальных параметров/компонентов браузера. Преимущество fingerprint’a в том что он нигде персистентно не хранится и генерируется только в момент логина и рефреша.

  • Библиотека для хеширования: https://github.com/Valve/fingerprintjs2
  • Более подробно: https://player.vimeo.com/video/151208427
  • Пример ф-ции получения такого хеша: https://gist.github.com/zmts/b26ba9a61aa0b93126fc6979e7338ca3

В случае если клиент не браузер, а мобильное приложение, в качестве fingerprint используем любую уникальную строку(тот же uuid ) персистентно хранящуюся на устройстве.

Рефреш токенов (api/auth/refresh-tokens):

Для использования возможности аутентификации на более чем одном девайсе необходимо хранить все рефреш токены по каждому юзеру. Я храню это список в PostgreSQL таблице(а надо бы в Redis’е). В процессе каждого логина создается запись с IP/Fingerprint и другой мета информацией, так званая рефреш-сессия.

  1. Клиент(фронтенд) проверяет перед запросом не истекло ли время жизни access token’на
  2. Если истекло клиент делает запрос на POST auth/refresh-tokens < fingerprint: string >в body и соответственно refreshToken куку.
  3. Сервер получает запись рефреш-сессии по UUID’у рефреш токена
  4. Сохраняет текущую рефреш-сессию в переменную и удаляет ее из таблицы
  5. Проверяет текущую рефреш-сессию:
    1. Не истекло ли время жизни
    2. На соответствие старого fingerprint’a полученного из текущей рефреш-сессии с новым полученным из тела запроса

    Tip: Для отправки запроса с куками для axios есть опция

    В момент рефреша то есть обновления access token’a обновляются ОБА токена. Но как же refresh token может сам себя обновить, он ведь создается только после успешной аутентификации ? refresh token в момент рефреша сравнивает себя с тем refresh token’ом который лежит в БД и вслучае успеха, а также если у него не истек срок, система рефрешит токены.

    Вопрос зачем refresh token’y срок жизни, если он обновляется каждый раз при обновлении access token’a ? Это сделано на случай, если юзер будет в офлайне более 60 дней, тогда придется заново вбить логин/пароль.

    1. Front-end делает кол POST: api/auth/logout c refreshToken в куке или бади (лучше в куки)
    2. Front-end удаляет локально сохраненный в памяти accessToken
    3. Back-end удаляет запись из таблицы refreshSessions по refreshToken

    accessToken умирает по истечению строка его жизни. Руками банить, удалять, хранить accessToken не нужно, это нарушает всю суть эксесс токена.

    В случае кражи access токена и refresh куки:

    1. Хакер воспользовался access token’ом
    2. Закончилось время жизни access token’на
    3. Клиент хакера отправляет refresh token и fingerprint
    4. Сервер смотрит fingerprint хакера
    5. Сервер не находит fingerprint хакера в рефреш-сессии и удаляет ее из БД
    6. Сервер логирует попытку несанкционированного обновления токенов
    7. Сервер перенаправляет хакера на станицу логина. Хакер идет лесом
    8. Юзер пробует зайти на сервер >> обнаруживается что refresh token отсутствует
    9. Сервер перенаправляет юзера на форму аутентификации
    10. Юзер вводит логин/пароль

    В случае кражи access токена, refresh куки и fingerprint’а:

    Стащить все авторизационные данные это не из легких задач, но все же допустим этот кейс как крайний и наиболее неудобный с точки зрения UX (без примера в кодовой базе supra-api-nodejs ).

    Предложу несколько вариантов решения данной проблемы:

    • Хранить IP или Subnet залогиненного клиента
    1. Хакер воспользовался access token’ом
    2. Закончилось время жизни access token’на
    3. Хакер отправляет refresh куку и fingerprint
    4. Сервер проверяет IP хакера, хакер идет лесом

    UX минус: нужно логинится с каждого нового IP.

    • Удалять все сессии в случае если refresh токен не найден
    1. Хакер воспользовался access token’ом
    2. Закончилось время жизни access token’на
    3. Хакер отправляет refresh куку и fingerprint
    4. На сервере создается новый refresh токен («от хакера»)
    5. Хакер получает новую пару токенов
    6. Юзер пробует отправить запрос на сервер >> обнаруживается что refresh токен не валиден
    7. Сервер удаляет все сессии юзера, в последствии чего хакер больше не сможет обновлять access токен
    8. Сервер создает новую сессию для пользователя

    UX минус: в каждом случае когда сервер не будет находить рефреш токен — будут сбрасиватся все сессии юзера на всех устройствах.

    Зачем все это ? JWT vs Cookie sessions

    Зачем этот весь геморой ? Почему не юзать старые добрые cookie sessions ? Чем не угодили куки ?

    Как работает OAuth 2.0 и OpenID Connect

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

    Как работает OAuth 2.0 и OpenID Connect

    В этой статье рассмотрим историю возникновения и схему работы. Разберемся в чем отличие OAuth 2.0 от OpenID Connect и что такое SSO.

    История возникновения OAuth

    Авторизацией через социальные сети никого уже не удивишь. Нажимаешь кнопку соц сети, вжух и ты авторизовался на новом сайте. Сайт получил твоё ФИО, фотку и прочие данные. Но так было не всегда.

    В «каменном веке» интернета все было проще. Вы просто давали свой логин и пароль от одного сервиса другому, чтобы тот вошел в вашу учетную запись и получил любую необходимую ему информацию.

    На заре становления Facebook просил у пользователей логин и пароль от Gmail аккаунта, чтобы отправить контактам приглашение. Такой подход имеет большую проблему: логин и пароль дают полный доступ к сервису. Поэтому был разработан стандарт OAuth.

    С помощью этого стандарта вы позволяете приложению считать данные или использовать функции другого приложения от вашего имени, не сообщая ему свой пароль. Класс!

    OAuth 1.0 не используется. Забудьте о нем. Используйте OAuth 2.0

    Главным недостатком OAuth 1.0 была слишком большая сложность данной версии.

    Начнем разбор OAuth 2.0 с ролей. Всего есть 4 роли:

    • Владелец ресурса.
    • Клиент.
    • Сервер ресурсов.
    • Авторизационный сервер.

    Далее мы рассмотрим каждую из ролей.

    Владелец ресурса
    Ресурсом являются данные, например ФИО, фотография, ваши сообщения в соц сетях, и прочее. Владелец ресурса это пользователь. При межсерверном общении владельцем ресурса может быть один из серверов.

    Сервер ресурсов
    На сервере ресурсов лежат ваши данные. В случае с примером выше ваши контакты Gmail это ресурс, а лежат они на серверах Gmail.

    Клиент
    Клиент это сервис, которому требуется доступ к вашим ресурсам. Например, Facebook требуется доступ к контактам Gmail.

    Авторизационный сервер
    В данном примере он принадлежит Google, так как он хранит ваши данные.

    Базовая схема протокола

    OAuth 2.0 основан на использовании базовых веб-технологий: HTTP-запросах, редиректах и т. п. Поэтому использование OAuth возможно на любой платформе с доступом к интернету и браузеру: на сайтах, в мобильных и desktop-приложениях, плагинах для браузеров.

    Вернемся к нашему примеру про Facebook и Gmail. На анимации ниже, я постарался схематично изобразить, как реализовать этот пример правильно с помощью Oauth2. Стоит учитывать, что у Google есть свой сервер авторизации, который отвечает за авторизацию на любом сервисе Google. Поэтому Gmail только хранит ресурсы, но не отвечает за авторизацию.

    Весь смысл в том, что Клиент должен получить каким-то образом от авторизационного сервера access_token . Способов этих четыре, о них мы поговорим дальше. Используя этот access_token Клиент может использовать его в запросах к Серверу ресурсов, чтобы получать какие-то данные.

    Это строка, которая является альтернативой логину и паролю.

    Особенности Access Token:

    • Ограниченное время жизни.
    • Его можно отозвать. Если есть подозрение, что токен украли, то мы просто запрещаем получать данные с помощью этого токена.
    • Компрометация токена не значит компрометирование логина и пароля. Из токена никак не получить логин и пароль.
    • По токену может быть доступна только часть данных (scope). Клиент запрашивает список разрешений, которые необходимы ему для работы, а Владелец ресурсов решает выдать такие права или нет. Например, можно выдать права только на просмотр списка контактов, тогда читать письма или редактировать контакты будет нельзя.

    Помимо access_token Авторизационный сервер может выдавать также refresh_token . Это токен, который позволяет запросить новый access_token без участия Владельца ресурсов. Время жизни у такого токена намного больше access_token и его потеря гораздо серьезнее.

    Вернемся к базовой схеме. Авторизационный сервер должен знать про каждого клиента, который делает к нему запрос. То есть, каждый клиент должен быть зарегистрирован. Зарегистрировав клиента мы получаем client_id и client_secret и обязаны передавать, как минимум client_id в каждом запросе.

    Не все клиенты могут гарантировать сохранность client_secret , поэтому он есть не у всех. Например, SPA без бэкенда, теоретически достать оттуда можно что угодно.

    Существует возможность регистрировать клиентов динамически: RFC 7591 и RFC 7592.

    Способы получения Access Token

    Всего есть 4 способа:

    • По авторизационному коду (Authorization Code Grant). Самый сложный и самый надежный способ.
    • Неявно (Implicit)
    • По логину и паролю пользователя (Resource Owner Password Credential). Только для безопасных клиентов, заслуживающих полного доверия.
    • По данным клиента (Client Credentials). Получаем токен по client_id и client_secret .

    Client Credentials

    Начнем разбор с самой простой схемы. Этот способ придуман для межсерверного взаимодействия. У нас есть два сервера API1 и API2, и им надо как-то общаться.

    1. API 1 идет в авторизационный сервер передает туда client_id и client_secret .

    2. Взамен API 1 получает access_token , с помощью которого может обратиться к API 2.

    3. API 1 обращается к API 2.

    4. API 2 получает запрос с access_token и обращается к авторизационному серверу для проверки действительности переданного токена (RFC 7662).

    Resource Owner Password Credential

    1. Владелец ресурсов передает свой логин и пароль Клиенту.
    2. Клиент отправляет Авторизационному серверу логин и пароль клиента, а так же свой client_id и client_secret .

    3. Если предоставленные пользователем учетные данные успешно аутентифицированы, сервер авторизации вернет ответ application/json , содержащий access_token :

    Authorization Code Grant

    Является одним из наиболее распространённых типов разрешения, поскольку он хорошо подходит для серверных приложений, где исходный код приложения и секрет клиента не доступны посторонним.

    1. Пользователь на сайте нажимает кнопку авторизации, например через Facebook.
    2. Происходит редирект на авторизационный сервер.
    3. Если активной сессии нет, то Пользователь должен залогиниться. Если активная сессия есть, то просто подтвердить авторизацию.

    Пример авторизационного запроса

    • response_type — Обозначает тип учетных данных, которые возвращает авторизационный сервер. Для этого способа значение должно быть code .
    • redirect_uri — URL-адрес, на который авторизационный сервер будет перенаправлять браузер после авторизации пользователя. Код авторизации будет доступен в параметре code .

    4. Если все пойдет хорошо, вы получите ответ HTTP 302. Код авторизации включен в конце URL-адреса: в параметре ?code=SplewFEFofer

    Так как code попадает в браузер и ничем не защищен, то это точка уязвимости. Поэтому на авторизационный код накладываются следующие ограничения:

    • Код одноразовый
    • Время жизни кода очень мало

    5. Теперь, когда у вас есть код авторизации, вы должны обменять его на токены. Используя извлеченный код авторизации из предыдущего шага, вам нужно будет выполнить POST на URL-адрес токена.

    6. Если все пойдет хорошо, вы получите ответ HTTP 200 с полезной нагрузкой, содержащей значения access_token , refresh_token , id_token и token_type :

    7. Чтобы вызвать ваш API из обычного веб-приложения, приложение должно передать полученный токен доступа в заголовке авторизации вашего HTTP-запроса.

    Implicit Grant

    Теперь у нас сайт без бэкенда — SPA.

    1. Пользователь на сайте жмет на кнопку, происходит редирект на сервер авторизации.
    2. Пользователь вводит логин пароль, если он не авторизован.
    3. Происходит редирект обратно, но access_token возвращается в URL сразу: https://domain.com/back_path#access_token=8ijfwWEFFf0wefOofreW6rglk .

    Адресная строка никак не шифруется, а так как access_token попадает в адресную строку, то существует множество способов его перехватить. Например, провайдер видит все адреса, по которым вы переходите.

    При использовании схемы Code Grant вы передаете токен в куке. Куки передаются в заголовке запроса. При использовании https соединения, заголовки шифруются. Поэтому достать токен из куки при передаче невозможно.

    OpenID Connect

    OAuth 2.0 разработан только для авторизации — для предоставления доступа к данным и функциям от одного приложения другому. OpenID Connect (OIDC) — это тонкий слой поверх OAuth 2.0, добавляющий сведения о логине и профиле пользователя, который вошел в учетную запись.

    OpenID Connect позволяет реализовывать сценарии, когда единственный логин можно использовать во множестве приложений, — этот подход также известен как single sign-on (SSO)

    Поток (flow) OpenID Connect выглядит так же, как и в случае OAuth 2.0. Единственная разница в том, что в первичном запросе используемый конкретный scope — openid, — а Клиент в итоге получает как access_token , так и id_token .

    ID Token — это особым образом отформатированная строка символов — JSON Web Token или JWT. Сторонним наблюдателям JWT может показаться непонятной абракадаброй, однако Клиент может извлечь из JWT различную информацию, такую как ID, имя пользователя, время входа в учетную запись, срок окончания действия ID Token’а, наличие попыток вмешательства в JWT.

    В случае OIDC также имеется стандартный способ, с помощью которого Клиент может запросить дополнительную информацию о пользователе от Сервера авторизации, например, адрес электронной почты, используя access_token .

    Заключение

    Подведем итог. OAuth 2.0 это простой протокол авторизации, основанный на HTTP, что дает возможность применять его практически на любой платформе. Он имеет хорошую документацию, и большинство крупных площадок его поддерживают. Так что если вы решили использовать этот протокол в своем проекте — это хороший выбор.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *