Создайте токены веб-аутентификации jwt в ember-cli-mirage (или любой JavaScript) для использования в приложении ember - PullRequest
1 голос
/ 16 января 2020

Я работаю в команде Ember, которая реализовала djangorestframework-simplejwt для нашей безопасности API. Это хорошее API-решение, но через некоторое время наш пользователь-мираж вышел из системы и не смог снова войти в наше приложение (для тестирования, разработки). Я проследил проблему до того, как работает jwt, и до того, что я вставил токены stati c jwt в нашу конечную точку конфигурации / входа mirage.

jwt или JSON веб-токены содержат дату окончания срока действия, установленную на сервере. По истечении этой даты истечения срока действия клиент больше не может быть авторизован в приложении, пока сервер не отправит новый токен с future сроком действия. Это было проблемой для нашего Mirage ENV, потому что конечная точка mirage для / login возвращала токен c jwt, который я скопировал / вставил из нашего внутреннего ответа. Обходной путь состоял в том, чтобы получить новые токены из нашего бэкэнда, вставить их в конфигурацию mirage и использовать их до истечения срока действия, что не является истинным постоянным решением этой проблемы.

1 Ответ

1 голос
/ 16 января 2020

После МНОГО проб и ошибок (и слишком многого узнав о jwt) я придумал это решение, которое создает действительный токен jwt с датой истечения 7 дней в будущем. Для этого требуется только crypto- js (npm install crypto- js), очень легкая библиотека со множеством криптографических функций, но без зависимостей:

import CryptoJS from 'CryptoJS';

const generateTokens = function(secretKey) { // fn to generate jwt access and refresh tokens with live date (+7 days) expiration
  let newEpochDate = new Date().valueOf();
  newEpochDate += 6.048e8; // add 7 days padding
  newEpochDate = Math.trunc(newEpochDate / 1000); // convert to Java epoch date value
  let tokenObjBase = {
    'typ': 'JWT',
    'alg': 'HS256'
  };
  let tokenObjAccess = {
    'token_type': 'access',
    'exp': newEpochDate,
    'jti': '83bc20a2fb564aa8937d167586166f67',
    'user_id': 24865
  };
  let tokenObjRefresh = {
    'token_type': 'refresh',
    'exp': newEpochDate,
    'jti': '83bc20a2fb564aa8937d167586166f67',
    'user_id': 24865
  };

  let base64urlEncode = function (obj) {
    let base64url = CryptoJS.enc.Utf8.parse(JSON.stringify(obj)).toString(CryptoJS.enc.Base64);
    base64url = base64url.replace(/=/g, '').replace(/\//g, '_').replace(/\+/g, '-'); // crypto-js doesn't have base64url encoding; we must manually make the tokens URL safe
    return base64url;
  }
  let tokenBase = base64urlEncode(tokenObjBase);
  let tokenAccess = base64urlEncode(tokenObjAccess);
  let tokenRefresh = base64urlEncode(tokenObjRefresh);

  let signatureAccessArray = CryptoJS.HmacSHA256(tokenBase + '.' + tokenAccess, secretKey); // crypto-js returns a "wordarray" which must be stringified back to human readable text with a specific encoding
  let signatureAccess = signatureAccessArray.toString(CryptoJS.enc.Base64).replace(/=+$/, '').replace(/\//g, '_').replace(/\+/g, '-'); // crypto-js doesn't have base64url encoding; we must manually make the tokens URL safe
  let signatureRefreshArray = CryptoJS.HmacSHA256(tokenBase + '.' + tokenRefresh, secretKey);
  let signatureRefresh = signatureRefreshArray.toString(CryptoJS.enc.Base64).replace(/=+$/, '').replace(/\//g, '_').replace(/\+/g, '-'); // crypto-js doesn't have base64url encoding; we must manually make the tokens URL safe

  return {tokenRefresh: tokenBase + '.' + tokenRefresh + '.' + signatureRefresh, tokenAccess: tokenBase + '.' + tokenAccess + '.' + signatureAccess};
}

export default function() { // ...rest of mirage/config.js

// you may also need this in your ember-cli-build:
app.import('node_modules/crypto-js/crypto-js.js', {
  using: [
    { transformation: 'amd', as: 'CryptoJS' }
  ]
});

This fn может вызываться любым маршрутом в файле конфигурации: let tokens = generateTokens('thisisnotarealsecretkey');

Возвращает объект с токеном «access» и токеном «refre sh», двумя типами токенов, необходимыми для нашего django Настройка JWT. Настройте tokenObjBase, tokenObjAccess и tokenObjRefre sh в соответствии с настройками вашего бэкенда.

Основную c структуру токена jwt можно найти здесь: https://jwt.io/

Подводя итог, маркер jwt имеет три строки, разделенные двумя точками (.).

Первая строка - это tokenObjBase, переданная через JSON .stringify (), затем преобразованная в значение base64URL. Эта URL часть важна, потому что обычные кодировки base64 не удаляют символы =, + и /, которые не являются "безопасными для сети". TokenObjBase должен содержать свойства typ и alg и ничего больше.

Вторая строка - это ваша полезная нагрузка (здесь tokenObjAccess или tokenObjRefre sh) и обычно содержит информацию о пользователе (имя, идентификатор, et c), а также значение даты эпохи, которое представляет дату истечения срока действия токена. Эта полезная нагрузка obj, как и первая, передается через JSON .stringify (), а затем преобразуется в значение base64URL. НЕ помещайте конфиденциальные данные в эти первые два объекта js, они вообще не «зашифрованы». Кодировка Base64 может быть изменена любым пользователем, имеющим компьютер и Google.

Третья строка - это jwt "signature". Он создается путем объединения первых двух строк base64 с точкой (.) В середине, а затем передачи их через алгоритм шифрования HS256 (HMA C -SHA256).

Затем все три строки (две base64URL строки и зашифрованная строка HS256) объединяются: base64URL (tokenObjBase) + '.' + base64URL (tokenObjPayload) + '.' + signatureHS256

Надеюсь, это поможет всем, у кого возникли проблемы с постоянным выходом jwt из списка пользователей Ember в своих приложениях!

...