Создание заголовка формы JWT и полезной нагрузки

Я использую node js для создания jwt на моем внутреннем сервере. Я использую библиотеку для подписи/проверки JWT, и она работает нормально. как только один jwt.io я вставляю токен, который я получил, когда я вхожу в систему, и я вижу свои данные в полезной нагрузке. Итак, проблема в том, что я пытаюсь сгенерировать подпись из заголовка, а полезная нагрузка, которую я получил обратно в jwt.io, - это то, что я пытался сделать, но это не сработало, и я немного запутался. для подписи используется алгоритм по умолчанию HS256.

const crypto = require("crypto");

// encode base64 the header
let jsonHeader = JSON.stringify({
  alg: "HS256",
  typ: "JWT",
});
let bs64header = Buffer.from(jsonHeader).toString("base64").split("=")[0];
console.log("bs64header :>>\n ", bs64header); //look the same as the token i got

// encode vase64 the payload
let jsonPayload = JSON.stringify({
  id: "5eb20004ac94962628c68b91",
  iat: 1589125343,
  exp: 1589989343,
  jti: "37743739b1476caa18ca899c7bc934e1aba63ba1",
});
let bs64payload = Buffer.from(jsonPayload).toString("base64").split("=")[0];
console.log("bs64Payload :>> \n", bs64payload); //look the same as the token i got

// TRY to generate the signature from the Base64Header and Base64Payload
// with the secret code that i used to sign the JWT
let secret = "0d528cb666023eee0d44e725fe9dfb751263d2f68f07998ae7388ff43b1b504f";
let signature = bs64header + "." + bs64payload;

let hashed = crypto
  .createHash("sha256", secret)
  .update(signature)
  .digest("hex");

console.log("hashed :>> \n", hashed);

let bs64signature = Buffer.from(hashed).toString("base64").split("=")[0];
console.log("bs64signature>>", bs64signature); //This is where i got stuck.

// let jwt = bs64header + "." + bs64payload + "." + bs64signature;
// console.log("jwt>>", jwt);



person Ngalla Juke    schedule 10.05.2020    source источник
comment
Почему вы сами генерируете строку jwt ?? Думаю, вам нужно изучить npmjs.com/package/jsonwebtoken. Это значительно сократит ваш код и все ручные шаги, которые вы выполняете для создания токена. Токены действительно чувствительны, одна ошибка в структуре, и вы не сможете ее проверить или прочитать.   -  person Akhilesh Sharma    schedule 10.05.2020
comment
я использовал jwt.sign() для создания токена и jwt.verify(), чтобы проверить, хорош ли токен. Но когда я хотел создать корень выхода из системы для пользователя, эти два метода были небезопасными. поэтому мне нужно было создать свой собственный токен с некоторыми пользовательскими утверждениями в полезной нагрузке, чтобы позже выполнить проверку!   -  person Ngalla Juke    schedule 12.05.2020
comment
Вы можете добавлять собственные утверждения во время создания токенов с помощью JSONWebToken lib. Что именно вы имеете в виду под тем, что методы небезопасны? Вы могли бы предоставить область роли в своем токене, чтобы проверить, что это за пользователь.   -  person Akhilesh Sharma    schedule 12.05.2020
comment
На самом деле я сам виноват, что не провел больше исследований о JWT и не попытался понять его. Также я согласен с вашим первым комментарием, использование npmjs.com/package/jsonwebtoken также будет более полезным. но в то же время это было хорошее упражнение, помогающее лучше понять, как работает JWT и как сделать это самостоятельно.   -  person Ngalla Juke    schedule 14.05.2020


Ответы (1)


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

Я протестировал его в runkit, а также проверил, какие выходные данные должны быть, используя jwt.io. Результат кажется таким же, поэтому я почти уверен, что это работает.

Изменения

  • Создал функцию для base64 кодирования объектов и строк.
  • Создана функция, позволяющая использовать в строках base64 безопасный набор символов URL.
  • Изменено crypto.createHash() на crypto.createHmac(), чтобы действительно можно было использовать секретный ключ.
// base64 encode the data
function bs64encode(data) {
  if (typeof data === "object") {
    data = JSON.stringify(data);
  }

  return bs64escape(Buffer.from(data).toString("base64"));
}

// modify the base64 string to be URL safe
function bs64escape(string) {
  return string.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
}



// base64 encode the header
let bs64header = bs64encode({
  alg: "HS256",
  typ: "JWT"
});

console.log("bs64header :>>\n ", bs64header);


// base64 encode the payload
let bs64payload = bs64encode({
  id: "5eb20004ac94962628c68b91",
  iat: 1589125343,
  exp: 1589989343,
  jti: "37743739b1476caa18ca899c7bc934e1aba63ba1"
});

console.log("bs64payload :>> \n", bs64payload);


// generate the signature from the header and payload
let secret = "0d528cb666023eee0d44e725fe9dfb751263d2f68f07998ae7388ff43b1b504f";
let signature = bs64header + "." + bs64payload;

let bs64signature = bs64escape(crypto
  .createHmac("sha256", secret)
  .update(signature)
  .digest("base64"));

console.log("bs64signature>>", bs64signature);


let jwt = bs64header + "." + bs64payload + "." + bs64signature;

console.log("jwt>>", jwt);
person Daemon Beast    schedule 10.05.2020
comment
Спасибо!! Эта работа тоже. Я также предлагаю решение, прежде чем я проверю ваш ответ. Итак, чего мне не хватало, так это создания функции, позволяющей строкам base64 использовать безопасный набор символов URL. - Crypto.createHash() изменен на crypto.createHmac(), чтобы можно было использовать секретный ключ. - person Ngalla Juke; 12.05.2020