Почему ruby-jwt прекратил декодирование JWT после обновления gem с 1.3.0 до 2.2.2?

#ruby-on-rails #ruby #heroku #jwt

#ruby-на-рельсах #рубиновый #героку #jwt

Вопрос:

У меня возникла проблема с моей реализацией ruby-jwt после обновления:

  • Рельсы 4.1.6 — 4.2.11.3
  • Ruby 2.1.4 — 2.6.6
  • ruby-jwt gem с 1.3.0 до 2.2.2.

Он не будет декодировать токен после обновления и возвращает «Неверную информацию для входа». сообщение об ошибке от метода Login класса decode .

Это журнал успешного входа в исходную версию:

 2020-12-04T09:51:42.814533 00:00 app[web.1]: I, [2020-12-04T09:51:42.814461 #8]  INFO -- : Started POST "/api/p/v1/users/verify" for 54.210.159.54 at 2020-12-04 09:51:42  0000
2020-12-04T09:51:42.859735 00:00 app[web.1]: I, [2020-12-04T09:51:42.859575 #8]  INFO -- : Processing by API::P::V1::UsersController#verify as JSON
2020-12-04T09:51:42.859766 00:00 app[web.1]: I, [2020-12-04T09:51:42.859707 #8]  INFO -- :   Parameters: {"login"=>"long token....................."}
2020-12-04T09:51:43.483446 00:00 heroku[router]: at=info method=POST path="/api/p/v1/users/verify" host=rails-api-app.herokuapp.com request_id=7f6dbb16-df78-4714-9b7c-b984905a2d6b fwd="54.210.159.54" dyno=web.1 connect=1ms service=674ms status=200 bytes=1457 protocol=https
2020-12-04T09:51:43.481107 00:00 app[web.1]: I, [2020-12-04T09:51:43.481016 #8]  INFO -- : Completed 200 OK in 621ms (Views: 477.0ms | ActiveRecord: 25.7ms)
 

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

 2020-12-04T09:48:11.749514 00:00 app[web.1]: I, [2020-12-04T09:48:11.749444 #16]  INFO -- : Started POST "/api/p/v1/users/verify" for 54.210.159.54 at 2020-12-04 09:48:11  0000
2020-12-04T09:48:11.818319 00:00 app[web.1]: I, [2020-12-04T09:48:11.818203 #16]  INFO -- : Processing by API::P::V1::UsersController#verify as JSON
2020-12-04T09:48:11.818504 00:00 app[web.1]: I, [2020-12-04T09:48:11.818425 #16]  INFO -- :   Parameters: {"login"=>"long token....................."}
2020-12-04T09:48:11.892237 00:00 app[web.1]: I, [2020-12-04T09:48:11.892151 #16]  INFO -- : Rendered ActiveModel::Serializer::Null with Hash (0.35ms)
2020-12-04T09:48:11.892681 00:00 app[web.1]: I, [2020-12-04T09:48:11.892583 #16]  INFO -- : Completed 400 Bad Request in 74ms (Views: 22.9ms | ActiveRecord: 9.0ms)
2020-12-04T09:48:11.893186 00:00 app[web.1]: I, [2020-12-04T09:48:11.893118 #16]  INFO -- : source=rack-timeout id=89c370e4-54e2-4442-83b2-d0c19b67c027 wait=6ms timeout=15000ms service=145ms state=completed
2020-12-04T09:48:11.894875 00:00 heroku[router]: at=info method=POST path="/api/p/v1/users/verify" host=rails-api-app.herokuapp.com request_id=89c370e4-54e2-4442-83b2-d0c19b67c027 fwd="54.210.159.54" dyno=web.1 connect=0ms service=151ms status=400 bytes=406 protocol=https
 

На стороне сервера:

и Encryptable модуль с Login классом и Decode модулем:

 module RailsAppName
  module Encryptable
    class Login
      def self.decode(encrypted_payload, secret)
        begin
          new(Decoder.decode(encrypted_payload, secret))
          rescue JWT::DecodeError
            new({ valid: false, error_message: 'Invalid login information.' })
          rescue JWT::ExpiredSignature
            new({ valid: false, error_message: 'The signature has expired.' })
        end
      end
    end

    module Decoder
      DECODER              = JWT
      EXPIRATION           = 10
      ENCRYPTION_ALGORITHM = "HS512"
    
      def self.decode(encrypted_payload = {}, secret = "")
        DECODER.decode(
          encrypted_payload,
          secret,
          ENCRYPTION_ALGORITHM
        ).first
      end
    
      def self.encode(payload = {}, secret = "")
        prepare!(payload)
    
        DECODER.encode(
          payload,
          secret,
          ENCRYPTION_ALGORITHM
        )
      end
    
      private
    
      def self.prepare!(payload)
        payload.merge! exp: expiration_time
      end
    
      def self.expiration_time
        EXPIRATION.minutes.from_now.to_i
      end
    end
  end
end
 

Клиентская сторона:

 def verify(email, password)
  payload = { email: email, password: password }
  encrypted_payload = { login: RubyClient::JWTEncryptable.encode(payload) }.to_json
    
  response = public_client.post('/users/verify', { body: encrypted_payload })

  if response.code == 200
    { user_token: RubyClient::JWTEncryptable.encode(response["user"]), user: response["user"] }
  else
    { error: response['message'] }
  end
end
 

Ответ №1:

После тщательного прочтения документации ruby-jwt.

Изменение decode метода на следующий работает для меня:

 module Decoder
  DECODER              = JWT
  EXPIRATION           = 10
  ENCRYPTION_ALGORITHM = { algorithm: 'HS512' }

  def self.decode(encrypted_payload = {}, secret = "")
    DECODER.decode(
      encrypted_payload,
      secret,
      true,
      ENCRYPTION_ALGORITHM
    ).first
  end
end