Проверка подписи JWT не удалась

Я пытаюсь реализовать свою собственную аутентификацию, используя токены JWT. Я генерирую токены jwt при загрузке Java Spring.

Я использую этот веб-сайт для создания строки в кодировке Base64, которая будет использоваться в качестве секрета jwt: https://www.devglan.com/online-tools/hmac-sha256-online?ref=blog.tericcabrel.com

Это соответствующий загрузочный код Spring:

private Key getSignInKey() {
    byte[] keyBytes = Decoders.BASE64.decode(secretKey);
    return Keys.hmacShaKeyFor(keyBytes);
}
Jwts
        .builder()
        .setClaims(extraClaims)
        .setSubject(userDetails.getUsername())
        .setIssuedAt(new Date(System.currentTimeMillis()))
        .setExpiration(new Date(System.currentTimeMillis() + expiration))
        .signWith(getSignInKey(), SignatureAlgorithm.HS256)
        .compact();

Всё работает, проблема не здесь. Проблема возникает на стороне nextjs, где я пытаюсь проверить токен jwt, который я получаю из API после входа в систему:

export async function verifyAuth() {
  const token = cookies().get('user-token')

  if (!token) {
    return null
  }

  const jwtSecretKey = getJwtSecretKey()

  const { payload } = await jwtVerify(token.value, new TextEncoder().encode(jwtSecretKey))

  return payload as JwtPayload
}

Это продолжает вызывать следующее исключение, хотя я использую тот же секретный ключ, сгенерированный веб-сайтом выше (getJwtSecretKey просто возвращает переменную env из .env, а я использую jose):

digest: "3414803446"

⨯ JWSSignatureVerificationFailed: signature verification failed

at async verifyAuth (./lib/auth.ts:74:25)

at async Home (./app/page.tsx:11:18)

Что я здесь делаю не так?

возможно, getJwtSecretKey() не получает правильный секрет - вы говорите, что да, но, возможно, это не так - как BASE64.decode(secretKey) то же самое, что и new TextEncoder().encode(jwtSecretKey) ... если secretKey и jwtSecretKey имеют одно и то же значение по основанию 64, то это может объяснить это

Jaromanda X 29.06.2024 10:46

@JaromandaX да, getJwtSecretKey получает правильный секрет, он используется на серверной стороне так же, как secretKey Значение — это строка в кодировке Base64, которую я получил с веб-сайта. Я понимаю вашу точку зрения: поскольку я декодирую ключ на сервере, мне также следует декодировать его на клиенте, а не кодировать, верно?

CodingCoder 29.06.2024 11:01

понятия не имею... но BASE64.decode и TextEncoder().encode не приводят к одному и тому же результату... возможно, вам нужно везде декодировать base64 (не знаю, что вы подразумеваете под клиентом, если это в браузере, вы используете JWT неправильный)

Jaromanda X 29.06.2024 11:58

Почему вы используете new TextEncoder().encode(jwtSecretKey)? Это выглядит неправильно.

Bergi 29.06.2024 13:43

Кстати, getSignInKey надо писать getSigningKey

Bergi 29.06.2024 13:43
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
5
71
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Секрет, передаваемый в процессе подписи, декодируется из строки base64, прежде чем использоваться в качестве секрета подписи. Вы должны сделать то же самое, прежде чем передавать секрет jose, в противном случае new TextEncoder().encode(jwtSecretKey) просто использует закодированные байты в качестве секрета.

Это в Node.js

const secret = Buffer.from(jwtSecretKey, 'base64')

Было бы эквивалентно

keyBytes = Decoders.BASE64.decode(secretKey);

Другие вопросы по теме