Как подписать JWT?

Я пытаюсь защитить Sinatra API.

Я использую ruby-jwt для создания JWT, но не знаю, чем именно его подписать.

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


person Hugo    schedule 04.02.2015    source источник
comment
@joelparkerhenderson Я прокомментировал ваш ответ, но так и не получил на него ответа. Хотя мне помогло. Я отмечу это, но, пожалуйста, ответьте.   -  person Hugo    schedule 09.02.2015
comment
@joelparkerhenderson Я проголосовал за ответ, но не принял его.   -  person Hugo    schedule 09.02.2015
comment
@joelparkerhenderson Я только сейчас увидел, спасибо. Это хороший ответ. Я не мог найти ничего в Интернете о том, какой хороший подход был бы для этого, и это действительно довольно просто.   -  person Hugo    schedule 09.02.2015


Ответы (3)


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

Например, используйте гем dot env и файл .env с такой записью:

JWT_KEY=YOURSIGNINGKEYGOESHERE

Я лично генерирую ключ, используя простую случайную шестнадцатеричную строку:

SecureRandom.hex(64)

Шестнадцатеричная строка содержит только 0-9 и a-f, поэтому строка безопасна для URL.

person joelparkerhenderson    schedule 04.02.2015
comment
Хорошо, но что я должен использовать для генерации фактического ключа? Я думаю что-то вроде Base64.encode64(SecureRandom.random_bytes(128)). Все хорошо? Должен ли он быть длиннее или отличаться? - person Hugo; 04.02.2015

Для стратегии открытого и закрытого ключа RS256 вы можете использовать Ruby OpenSSL lib:

Генерация ключей:

key = OpenSSL::PKey::RSA.new 2048

open 'private_key.pem', 'w' do |io| io.write key.to_pem end
open 'public_key.pem', 'w' do |io| io.write key.public_key.to_pem end

Загрузите ключ из файла .pem для подписи токена:

priv_key = OpenSSL::PKey::RSA.new File.read 'private_key.pem'
token = JWT.encode payload, priv_key, 'RS256'

Загрузите ключ из файла .pem в токен Verify (создайте для этого промежуточное ПО):

      begin
        # env.fetch gets http header
        bearer = env.fetch('HTTP_AUTHORIZATION').slice(7..-1)
        pub_key = OpenSSL::PKey::RSA.new File.read 'public_key.pem'
        payload = JWT.decode bearer, pub_key, true, { algorithm: 'RS256'}
        
        # access your payload here
  
        @app.call env

      rescue JWT::ExpiredSignature
        [403, { 'Content-Type' => 'text/plain' }, ['The token has expired.']]
      rescue JWT::DecodeError
        [401, { 'Content-Type' => 'text/plain' }, ['A token must be passed.']]
      rescue JWT::InvalidIssuerError
        [403, { 'Content-Type' => 'text/plain' }, ['The token does not have a valid issuer.']]
      rescue JWT::InvalidIatError
        [403, { 'Content-Type' => 'text/plain' }, ['The token does not have a valid "issued at" time.']]
      end

Чтобы использовать ключ RSA в .env вместо загрузки файла, вам нужно будет использовать gem 'dotenv' и импортировать ключ как однострочную переменную с использованием новой строки '\n'. проверьте это ">вопрос о том, как это сделать. пример:

PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\nmineminemineminemine\nmineminemineminemine\nmineminemine...\n-----END PUBLIC KEY-----\n"

в качестве переменной .env PUBLIC_KEY загрузка ключа изменится на это:

key = OpenSSL::PKey::RSA.new ENV['PUBLIC_KEY']
person Marcelo Fonseca    schedule 31.01.2019

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

Как указано в этом ответе, секретные ключи должны генерироваться случайным образом. Однако вы по-прежнему хотите, чтобы ключ сохранялся для использования во всем приложении. Используя дайджест пароля из bcrypt, вы фактически используете хешированный ключ, полученный из базового секретного ключа (пароля). Поскольку хеш является случайным, это не надежный секретный ключ для использования, как вы заявили.

Предыдущий ответ с использованием SecureRandom.hex(64) — отличный способ создать начальный базовый ключ приложения. Однако в производственной системе вы должны принять это как переменную конфигурации и сохранить для последовательного использования при нескольких запусках вашего приложения (например, после перезагрузки сервера вы не должны аннулировать все ваши пользовательские JWT) или для нескольких распределенные серверы. В этой статье приводится пример извлечения секретного ключа из переменной среды для rails.

person Control Complex    schedule 12.11.2015