Добавляем refresh token

Разбираемся детально ху из ху

  1. OpenID — для проверки учетных данных пользователя (identification & authentication).
  2. OAuth — про то, чтобы получать доступ к чему-то.
  3. OpenID Connect — и про и то, и про другое одновременно.

OpenID 1.0OpenID 2.0

  • User –> App: Привет, это Миша.
  • App –> Authority: Вот «это» Миша?
  • Authority и User общаются тет-а-тет.
  • Authority –> App: Да, это Миша.

OpenID Attribute Exchange 1.0

  • User –> App: Привет, это Миша.
  • App –> Authority: Вот «это» Миша? И если это Миша, то пришлите мне его email.
  • Authority и User общаются тет-а-тет.
  • Authority –> App: Да, это Миша. И его email [email protected].xxx.

OAuth 1.0

  • App –> User: Mы бы хотели получить ваши картинки с другого сервера.
  • Authority и User общаются тет-а-тет.
  • Authority –> App: Вот вам билет (access token) на 15 минут.
  • App –> Third-party server: Нам тут по билету можно получить фотографии для этого пользователя.

OAuth 2.0OpenID Connect

  • Проверять учетные данные пользователя.
  • Получать профиль пользователя (или его части).

Взгляд сверху

Как мы знаем из раздела «», OpenID Сonnect нужен, чтобы получить у пользователя его учетные данные и проверить их. OAuth 2.0 нужен, чтобы получать токены доступа и с ними обращаться к ресурсам.

Терминология OAuth2 & OpenID Connect

  • OpenID Connect Provider (OP)
  • Client
  • User
  • Scope
    • Identity scopes – openid, profile, email
    • Resource scopes – various API
  • Authentication/Token Request
  • Identity Token
  • Access Token
  • Refresh Token

C_WaitForSlotEvent()

CK_DEFINE_FUNCTION(CK_RV, C_WaitForSlotEvent)(
	CK_FLAGS			flags,
	CK_SLOT_ID_PTR		pSlot,
	CK_VOID_PTR			pReserved
);

Назначение

Функция отслеживает события, происходящие со слотами системы (подключение или отключение токена). Параметр flags определяет, заблокирован ли вызов C_WaitForSlotEvent (т.е. находится ли функция в режиме ожидания события); pSlot указывает на переменную типа CK_SLOT_ID, получающую ID слота, с которым произошло событие. Для получения подробной информации о событии необходимо вызвать функцию C_GetSlotInfo. Параметр pReserved зарезервирован для следующих версий библиотеки, и для данной версии должен иметь значение NULL_PTR.

На данный момент для использования в flags определен только один аргумент — CKF_DONT_BLOCK.

Каждое приложение, использующее библиотеку PKCS #11, имеет флаг для каждого слота, использующийся для отслеживания нераспознанных событий в слоте. При инициализации библиотеки C_Initalize все флаги событий слотов сбрасываются, т.е.независимо от наличия/отсутствия токенов очередь событий в слотах будет пуста.

Если при вызове C_WaitForSlotEvent выставлены флаг CKF_DONT_BLOCK и флаг наличия события в каком-либо слоте, функция возвращает ID того слота, в котором произошло событие в переменную, на которую указывает pSlot. Если во время вызова функции флаги выставлены у нескольких слотов, то библиотекой выбирается, какой флаг будет сброшен и возвращен ID слота. Если C_WaitForSlotEvent вызвана из нескольких потоков приложения, то при появлении одного события все ожидающие его потоки завершат ожидание и продолжат работу.

Если при вызове C_WaitForSlotEvent выставлен флаг CKF_DONT_BLOCK и нет выставленных флагов наличия события ни для одного из слотов, функция возвращает CKR_NO_EVENT и в этом случае содержимое переменной, на которую указывает pSlot, не определено.

Если при вызове C_WaitForSlotEvent сброшен флаг CKF_DONT_BLOCK, то функция выполняется аналогично описанному выше сценарию, за исключением того, что она будет заблокирована. Это означает, что если во время вызова функции нет выставленных флагов событий в слотах, C_WaitForSlotEvent будет ждать до тех пор, пока какой-нибудь из флагов не будет выставлен. Если C_WaitForSlotEvent находится в режиме ожидания (заблокирована), то вызов C_Finalize из другого потока прервет ожидание и завершит работу библиотеки, а C_WaitForSlotEvent вернет значение CKR_CRYPTOKI_NOT_INITIALIZED.

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

События регистрируются все время между вызовами C_Initalize и C_Finalize, т.е все время пока библиотека готова к использованию. При вызове C_WaitForSlotEvent первое событие из очереди изымается, пользователю возвращается ID слота, с которым оно произошло. Очередь становится короче на единицу.

Если требуется получить все события, то C_WaitForSlotEvent требуется вызвать столько раз, пока очередной вызов не вернет ошибку CKR_NO_EVENT, это указывает на то, что очередь событий пуста и новых больше не приходило.

Возвращаемые значения

CKR_OK – функция выполнена успешно.

Стандартные коды ошибок:

CKR_ARGUMENTS_BAD,

CKR_CRYPTOKI_NOT_INITIALIZED,

CKR_FUNCTION_FAILED,

CKR_GENERAL_ERROR,

CKR_HOST_MEMORY,

CKR_NO_EVENT.

Пример

CK_FLAGS flags = 0;
CK_SLOT_ID slotID;
CK_SLOT_INFO slotInfo;

.
.
/* Блокировка функции и ожидание события в слоте */
rv = C_WaitForSlotEvent(flags, &slotID, NULL_PTR);
assert(rv == CKR_OK);

/* Получение информации о состоянии слота */
rv = C_GetSlotInfo(slotID, &slotInfo);
assert(rv == CKR_OK);
.
.

Типы паролей

Все токены содержат некоторые секретные сведения, которые используются для подтверждения личности. Есть четыре различных способа, в которых эта информация может быть использована:

Токен со статическим паролем.

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

Токен с синхронно динамическим паролем.

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

Токен с асинхронным паролем.

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

Токен вызов-ответ.

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

Одноразовые пароли, синхронизированные по времени

Синхронизированные по времени одноразовые пароли постоянно меняются в установленное время, например, раз в минуту. Для этого должна существовать синхронизация между токеном клиента и сервером аутентификации. Для устройств, не подключённых к сети, эта синхронизация сделана до того, как клиент приобрёл токен.
Другие типы токенов синхронизируются, когда токен вставляется в устройство ввода.
Главная проблема с синхронизированными токенами состоит в том, что они могут рассинхронизоваться спустя какой-то большой период времени. Тем не менее, некоторые системы, такие как SecurID компании RSA, позволяют пользователю синхронизировать сервер с токеном путём ввода нескольких последовательных кодов доступа. Большинство из них не может иметь сменных батарей, следовательно, они имеют ограниченный срок службы.

Одноразовые пароли на основе математического алгоритма

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

C_GetSlotInfo

CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)(
	CK_SLOT_ID			slotID,
	CK_SLOT_INFO_PTR	pInfo
);

Назначение

Функция позволяет получить информацию о данном слоте. Информация о слоте возвращается в структуре типа CK_SLOT_INFO. slotID — ID слота, к которому подключен токен, pInfo указывает на переменную, которая получает информацию о слоте.

Возвращаемые значения

CKR_OK – функция выполнена успешно.

Стандартные коды ошибок:

CKR_ARGUMENTS_BAD,

CKR_CRYPTOKI_NOT_INITIALIZED,

CKR_DEVICE_ERROR,

CKR_FUNCTION_FAILED,

CKR_GENERAL_ERROR,

CKR_HOST_MEMORY,

CKR_SLOT_ID_INVALID.

Расширенные коды ошибок.

Пример

CK_ULONG ulCount;
CK_SLOT_ID_PTR pSlotList;
CK_SLOT_INFO slotInfo;
CK_TOKEN_INFO tokenInfo;
CK_RV rv;

rv = C_GetSlotList(CK_FALSE, NULL_PTR, &ulCount);
if ((rv == CKR_OK) && (ulCount > 0)) {
	pSlotList = (CK_SLOT_ID_PTR)malloc(ulCount*sizeof(CK_SLOT_ID));
	rv = C_GetSlotList(CK_FALSE, pSlotList, &ulCount);
	assert(rv == CKR_OK);
	
	/* Получение информации о первом слоте */
	rv = C_GetSlotInfo(pSlotList, &slotInfo);
	assert(rv == CKR_OK);

	/* Получение информации о токене в первом слоте */
	rv = C_GetTokenInfo(pSlotList, &tokenInfo);
	if (rv == CKR_TOKEN_NOT_PRESENT) {
		.
		.
	}
	.
	.
	free(pSlotList);
}

C_SetPIN

CK_DEFINE_FUNCTION(CK_RV, C_SetPIN)(
	CK_SESSION_HANDLE	hSession,
	CK_UTF8CHAR_PTR		pOldPin,
	CK_ULONG			ulOldLen,
	CK_UTF8CHAR_PTR		pNewPin,
	CK_ULONG			ulNewLen
); 
  • hSession — дескриптор сессии;
  • pOldPin — указатель на старый PIN-код Пользователя;
  • ulOldLen — длина старого PIN-кода в байтах;
  • pNewPin — указатель на новый PIN-код Пользователя;
  • ulNewLen — длина нового PIN-кода в байтах.

Данный стандарт позволяет значению PIN-кода содержать любой корректный UTF8 символ, но производители токена могут накладывать свои ограничения (только цифры?).

Назначение

Функция изменяет PIN-код пользователя, выполнившего авторизацию на токене. Если авторизация не выполнена, то функция производит смену PIN-кода CKU_USER (Пользователя).

Функция может быть вызвана только в сессиях «R/W Public Session», «R/W SO Functions» или «R/W User Functions». При попытке вызвать функцию в других сессиях будет возвращена ошибка CKR_SESSION_READ_ONLY.

Если токен имеет защищенный путь аутентификации (обозначается выставленным флагом CKF_PROTECTED_AUTHENTICATION_PATH в структуре CK_TOKEN_INFO), то это означает, что существует некий способ аутентификации пользователя без отправки PIN-кода приложению через библиотеку. Это возможно, если пользователь вводит PIN-код через PIN pad на самом токене или подключаемом к нему устройстве. Для изменения PIN-кода текущего пользователя таким образом параметры Для инициализации токена таким образом параметры pOldPin и pNewPinфункции C_InitToken должны быть равны NULL_PTR. Во время выполнения C_InitToken текущим пользователем будут введены cтарый и новый PIN-коды через защищенный путь аутентификации. Стандартом не определяется, как PIN pad должен использоваться при вводе двух PIN-кодов.

Если токен имеет защищенный путь аутентификации, отличный от PIN pad, то будет ли использоваться  C_SetPIN для смены PIN-кода текущего пользователя зависит от токена.

Функция обрабатывает входные параметры следующим образом.

  1. Если ulPinLen != 0 и pPin != NULL_PTR, то проверяется длина PIN-кода. Если длина не является допустимой, то возвращается значение CKR_PIN_LEN_RANGE. Если длина удовлетворяет условиям проверки, то проверяются права доступа для «CKU_USER» на основании предъявленных pPin и ulPinLen.
  2. Если ulPinLen != 0 и pPin == NULL_PTR, то возвращается ошибка CKR_ARGUMENTS_BAD.
  3. Если ulPinLen == 0 и pPin != NULL_PTR, то возвращается ошибка CKR_PIN_LEN_RANGE.
  4. Если ulPinLen == 0 и pPin == NULL_PTR, то отображается PIN Pad (в текущей реализации: возвращается ошибка CKR_ARGUMENTS_BAD).

Возвращаемые значения

CKR_OK – функция выполнена успешно.

Стандартные коды ошибок:

CKR_ARGUMENTS_BAD,

CKR_CRYPTOKI_NOT_INITIALIZED,

CKR_DEVICE_ERROR,

CKR_DEVICE_MEMORY,

CKR_DEVICE_REMOVED,

CKR_FUNCTION_CANCELED,

CKR_FUNCTION_FAILED,

CKR_GENERAL_ERROR,

CKR_HOST_MEMORY,

CKR_PIN_INCORRECT,

CKR_PIN_INVALID,

CKR_PIN_LEN_RANGE,

CKR_PIN_LOCKED,

CKR_SESSION_CLOSED,

CKR_SESSION_HANDLE_INVALID,

CKR_SESSION_READ_ONLY,

CKR_TOKEN_WRITE_PROTECTED.

Расширенные коды ошибок.

Пример

CK_SESSION_HANDLE hSession;
CK_UTF8CHAR oldPin[] = {"OldPIN"};
CK_UTF8CHAR newPin[] = {"NewPIN"};
CK_RV rv;

rv = C_SetPIN(hSession, oldPin, sizeof(oldPin), newPin, sizeof(newPin));
if (rv == CKR_OK) {
  .
  .
}

если Sendpulse не принимает пароль аккаунта

Обычно эта ошибка токена случается из-за невозможности определить браузером пользовательские точки доступа… такой баг частенько выскакивает, когда у нас открываются одновременно и ещё одна-две подобные сервисные вкладки!

Принцип решения доступа в аккаунт Sendpulse достаточно прост, но, неожиданность задачи входа на сайт рассылки, как  и говорилось, вводит в замешательство!

Вот сервисная страничка входа:

…и такое, к примеру, предупреждение:

Добавляем refresh token

Перезагрузка (как предлагает сервис) странички и перезапись пароля на этом этапе как правило не помогают.

Однако для некоторых владельцев весьма успешно способствует некоторая профилактика браузера, например — попробуем удалить куки сервиса рассылки и вообще — все личные данные аккаунта, чтобы как-то обновить токен:

1 — очистим данные сервиса: куки, пароли и кэш пр. пр.

В этой статье не стану пояснять подробно — как удаляются данные сервисов, — для этого есть иные полезные статьи:  (подробнее описано тут: удаляем ненужные пароли, куки… и здесь: удалить в браузере данные SendPulse).

Но в теме этого поста… и чтобы как-то натолкнуть читателя на мысль решения проблемы входа в аккаунт Сендпульс, напоминаю: очистка кук в браузере, к примеру, в Фаерфокс происходит в этих настройках адресной строки обозревателя:

(во всех остальных случаях различных браузеров решения аналогичны!)

Добавляем refresh token

Если это не помогло — предупреждение не исчезло… ничего страшного (профилактика браузера лишней не бывает))! — приступим к следующему варианту:

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

Проверьте ID токены с помощью сторонней библиотеки JWT

Если ваш бэкэнд написан на языке, не поддерживаемом Firebase Admin SDK, вы все равно можете проверить идентификационные токены. Сначала найдите стороннюю библиотеку JWT для вашего языка . Затем проверьте заголовок, полезную нагрузку и подпись идентификатора токена.

Убедитесь, что заголовок идентификатора токена соответствует следующим ограничениям:

Утверждения заголовка идентификатора токена
Алгоритм
Идентификатор ключа Должен соответствовать одному из открытых ключей, перечисленных по адресу

Убедитесь, что полезная нагрузка идентификатора токена соответствует следующим ограничениям:

Заявки на получение токена идентификатора
Время истечения Должно быть в будущем. Время измеряется в секундах с эпохи UNIX.
Выдается вовремя Должно быть в прошлом. Время измеряется в секундах с эпохи UNIX.
Зрительская аудитория Должен быть ваш идентификатор проекта Firebase, уникальный идентификатор вашего проекта Firebase, который можно найти в URL-адресе консоли этого проекта.
эмитент Должно быть , где — это тот же идентификатор проекта, который использовался для выше.
Тема Должна быть непустой строкой и должна быть пользователя или устройства.
Время аутентификации Должно быть в прошлом. Время, когда пользователь прошел аутентификацию.

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

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

Токен и смарт-карта

Наверно, самым надежным и простым в реализации способом двухфакторной аутентификации является использование криптографического токена или смарт-карты. Токен — это USB-устройство, которое является и считывателем, и смарт-картой одновременно. Первым фактором в таком случае является факт владения устройством, а вторым — знание его PIN-кода.

Использовать токен или смарт-карту, тут кому, что удобнее. Но исторически так сложилось, что в России больше привыкли использовать токены, так как они не требуют использования встроенных или внешних считывателей смарт-карт. У токенов есть и свои минусы. Например, на нем не напечатаешь фотографию.

На фотографии изображена типичная смарт-карта и считыватель.

Однако вернемся к корпоративной безопасности.

А начнем мы с домена Windows, ведь в большинстве компаний в России корпоративная сеть построена именно вокруг него.

Как известно, политики Windows-домена, настройки пользователей, настройки групп в Active Directory предоставляют и разграничивают доступ к огромному количеству приложений и сетевых сервисов.

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

как восстановить пароль sendpulse

На страничке входа, соответственно кликаем «Забыли пароль?».

…Через некоторое время на указанную почту придёт ссылка на страничку восстановления пароля Сендпульс.

Добавляем refresh token

Ну вот и всё — доступ восстановлен!

Напоминаю: все последующие манипуляции по безопасности вашего сервисного аккаунта проводить во вкладках Настройка аккаунта/Безопасность.

Добавляем refresh token

Если что-то не совсем ясно в моём описании, милости прошу к комментариям…

Делитесь соображениями…

На этом занавес представления опускается……на рампы пыль печальная ложится…

!..подписываясь на обновления mihalica.ru —…расстаёмся с невежеством..!

В случае кражи access токена, refresh куки и fingerprint’а (без примера в кодовой базе supra-api-nodejs):

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

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

Хранить 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 минус: в каждом случае когда сервер не будет находить рефреш токен — будут сбрасиватся все сессии юзера на всех устройствах.

Что такое, виды

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

  1. Для авторизации. В этом случае токен пригодится для входа в программу без пароля или для рейдов.
  2. При создании селфботов. Self Bots — специальные боты, созданные на основе Дискорд API, и предназначенные для улучшения учетной записи. Они работают с профилем пользователя не через страницу программы, как это происходит обычно, и могут отправлять сообщение. Для использования бота нужен токен, который доступен на консоли. Его нельзя никому давать, ведь при попадании информации в чужие руки возможны проблемы с учетной записью. Так, при наличии пользовательского Token Discord открывается доступ к чтению и отправке сообщений, а также другим опциям.

Преимущества входа в домен по токену

PIN-код от токена проще запомнить, так как он может быть намного проще пароля. Каждый наверняка хоть раз в жизни видел, как «опытный» пользователь мучительно не может с нескольких попыток аутентифицироваться в системе, вспоминая и вводя свой «безопасный» пароль.

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

При использовании токена для пользователя вход в систему выглядит следующим образом: после загрузки компьютера, он просто подключает токен к USB-порту компьютера, вводит 4-6 цифр и нажимает кнопку Enter. Скорость ввода цифр у обычных людей выше, чем скорость ввода букв. Поэтому PIN-код вводится быстрее.

Токены позволяют решить проблему «брошенного рабочего места» — когда пользователь уходит со своего рабочего места и забывает выйти из своей учетной записи.

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

C_GetMechanismList()

CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)(
	CK_SLOT_ID				slotID,
	CK_MECHANISM_TYPE_PTR	pMechanismList,
	CK_ULONG_PTR			pulCount
);

Назначение

Функция позволяет получить список механизмов, поддерживаемых токеном. SlotID — ID слота, к которому подключен токен; pulCount указывает на переменную типа CK_ULONG, куда возвращается количество механизмов. Список механизмов возвращается в структуре типа CK_MECHANISM_TYPE.

Указатель pMechanismList может иметь значение NULL_PTR. В этом случае функция возвращает только количество механизмов (но не список), для которых необходимо зарезервировать память.

Существует два варианта вызова функции C_GetMechanismList приложением:

  1. Если указатель pMechanismList имеет значение NULL_PTR, тогда C_GetMechanismList возвращает лишь количество механизмов (но не список). Содержимое указываемого pMechanismList буфера в таком случае не имеет смысловой нагрузки, и функция вернет CKR_OK.
  2. Если pMechanismList != NULL_PTR, тогда pMechanismList должен содержать размер (в формате CK_MECHANISM_TYPE элемента) указываемого pMechanismList буфера. Если размер буфера является достаточным для того, чтобы вместить в себя список, то список возвращается в нем и функция возвращает CKR_OK. В противном случае C_GetMechanismList возвращает CKR_BUFFER_TOO_SMALL. В обоих случаях *pMechanismList принимает значение, равное количеству механизмов.

Различные типы токенов поддерживают разное количество механизмов, более подробная информация доступна в 3.2.6 Механизмы стандарта PKCS#11 и 3.2.7 Механизмы расширения стандарта PKCS#11.

Возвращаемые значения

CKR_OK – функция выполнена успешно.

Стандартные коды ошибок:

CKR_ARGUMENTS_BAD,

CKR_BUFFER_TOO_SMALL,

CKR_CRYPTOKI_NOT_INITIALIZED,

CKR_DEVICE_ERROR,

CKR_DEVICE_MEMORY,

CKR_DEVICE_REMOVED,

CKR_FUNCTION_FAILED,

CKR_GENERAL_ERROR,

CKR_HOST_MEMORY,

CKR_SLOT_ID_INVALID,

CKR_TOKEN_NOT_PRESENT,

CKR_TOKEN_NOT_RECOGNIZED.

Расширенные коды ошибок.

Пример

CK_SLOT_ID slotID;
CK_ULONG ulCount;
CK_MECHANISM_TYPE_PTR pMechanismList;
CK_RV rv;

.
.
rv = C_GetMechanismList(slotID, NULL_PTR, &ulCount);
if ((rv == CKR_OK) && (ulCount > 0)) {
	pMechanismList = (CK_MECHANISM_TYPE_PTR) malloc(ulCount*sizeof(CK_MECHANISM_TYPE));
	rv = C_GetMechanismList(slotID, pMechanismList, &ulCount);
	if (rv == CKR_OK) {
    .
    .
	}
free(pMechanismList);
}

Проверьте ID токены с помощью Firebase Admin SDK

Firebase Admin SDK имеет встроенный метод проверки и декодирования идентификационных токенов. Если предоставленный токен идентификатора имеет правильный формат, срок его действия не истек и он подписан надлежащим образом, метод возвращает декодированный токен идентификатора. Вы можете получить пользователя или устройства из декодированного токена.

Следуйте инструкциям по установке Admin SDK, чтобы инициализировать Admin SDK с учетной записью службы. Затем используйте метод для проверки идентификатора токена:

Идентификация токена требует идентификационный номер проекта. Firebase Admin SDK пытается получить идентификатор проекта одним из следующих способов:

  • Если SDK был инициализирован с явным параметром приложения , SDK использует значение этого параметра.
  • Если SDK был инициализирован с учетными данными учетной записи службы, SDK использует поле объекта JSON учетной записи службы.
  • Если установлена ​​переменная среды , SDK использует ее значение в качестве идентификатора проекта. Эта переменная среды доступна для кода, выполняемого в инфраструктуре Google, такой как Google App Engine и Google Compute Engine.

Как узнать Дискорд-токен для аутентификации

Теперь рассмотрим следующий вопрос — как узнать свой токен в Дискорде. Сделайте следующие шаги:

  1. Войдите в свой профиль в веб-версии Discord.
  2. Жмите на кнопку Ctrl+Shift+I.

Добавляем refresh token

  1. Перейдите во кладку Network с правой стороны.
  2. В разделе Filter напишите /api/v6.
  3. Жмите на кнопку Ctrl+R.

Добавляем refresh token

  1. Войдите в любую вкладку, к примеру, Scince.
  2. Листайте справа до пункта, пока не найдете надпись autorization.
  3. Копируйте информацию и вставьте ее там, где это необходимо.

Добавляем refresh token

Как вариант, можно использовать Discord Token Generator. Суть состоит в установке программы и создании Дискорд-бота. Интерфейс софта интуитивно понятен, поэтому останавливаться на этом вопросе нет смысла.

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

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

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

куки ставим равную из выше созданной сессии
В ставим корневой роут контроллера () это важно, таким образом токен получат только те хендлеры которым он нужен( и ), остальные обойдутся(нечего зря почём отправлять sensitive data).

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

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

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

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

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

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