JWT: Як Інтегрувати JSON Web Tokens у Ruby on Rails

В Ruby on Rails для роботи з JWT (JSON Web Tokens) можна використовувати бібліотеку jwt. Вона дозволяє створювати, підписувати та перевіряти токени. JWT використовується для аутентифікації користувачів шляхом передачі закодованої інформації, такої як ідентифікатор користувача, в безпечний спосіб.

Ось детальний гайд, як використовувати jwt в Rails:

1. Встановлення бібліотеки

Спочатку додайте gem jwt в Gemfile вашого проекту:

gem 'jwt'

Після цього виконайте команду:

bundle install

2. Налаштування секретного ключа

JWT токени підписуються секретним ключем. Ви можете зберігати його в змінних середовища або у файлі конфігурації Rails.

У файл config/secrets.yml додайте:

development:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

Встановіть змінну оточення SECRET_KEY_BASE, або використайте іншу змінну, наприклад JWT_SECRET_KEY.

3. Створення токена

Припустимо, ви хочете створювати токен після того, як користувач успішно пройшов аутентифікацію (наприклад, в SessionsController).

require 'jwt'

class SessionsController < ApplicationController
  def create
    user = User.find_by(email: params[:email])
    
    if user && user.authenticate(params[:password])
      token = encode_token({ user_id: user.id })
      render json: { token: token }
    else
      render json: { error: 'Invalid email or password' }, status: :unauthorized
    end
  end

  private

  def encode_token(payload)
    JWT.encode(payload, Rails.application.secrets.secret_key_base)
  end
end

4. Декодування токена

Коли ви отримуєте запит із токеном (наприклад, у заголовку запиту), вам потрібно буде декодувати його, щоб отримати інформацію про користувача.

Ось приклад методу для декодування токена:

def decode_token(token)
  begin
    JWT.decode(token, Rails.application.secrets.secret_key_base, true, algorithm: 'HS256')[0]
  rescue JWT::DecodeError
    nil
  end
end

Цей метод поверне інформацію з токена або nil, якщо декодування не вдалося (наприклад, через неправильний або застарілий токен).

5. Додавання токена до заголовків

Зазвичай токен передається в заголовку запиту. Ви можете перевіряти токен у кожному запиті через before_action в контролері.

class ApplicationController < ActionController::API
  before_action :authorize_request

  private

  def authorize_request
    token = request.headers['Authorization']
    if token
      decoded_token = decode_token(token.split(' ').last)
      @current_user = User.find(decoded_token["user_id"]) if decoded_token
    else
      render json: { error: 'Unauthorized' }, status: :unauthorized
    end
  end
end

Тут використовується метод authorize_request, який спочатку перевіряє наявність токена в заголовку, потім намагається його розбити (токен зазвичай передається у вигляді Bearer <токен>), декодувати та знайти користувача за user_id.

6. Робота з терміном дії токенів

JWT підтримує додавання терміну дії токена через exp (expiration). Для цього можна додати поле в payload.

def encode_token(payload)
  exp = 24.hours.from_now.to_i
  payload[:exp] = exp
  JWT.encode(payload, Rails.application.secrets.secret_key_base)
end

Під час декодування можна додатково перевіряти термін дії:

def decode_token(token)
  begin
    decoded_token = JWT.decode(token, Rails.application.secrets.secret_key_base, true, algorithm: 'HS256')[0]
    if decoded_token['exp'] && Time.at(decoded_token['exp']) > Time.now
      decoded_token
    else
      nil
    end
  rescue JWT::ExpiredSignature
    nil
  rescue JWT::DecodeError
    nil
  end
end

7. Безпека

  • Використовуйте довгий і випадковий секретний ключ для підпису токенів.
  • Зашифровані токени повинні мати короткий термін дії (наприклад, кілька годин).
  • Використовуйте HTTPS для передачі токенів, щоб уникнути атаки типу «людина посередині» (MITM).

Висновок

Цей приклад показує основні кроки для інтеграції JWT з Ruby on Rails, включаючи створення, декодування та перевірку токенів. Ви можете розширити цей підхід, додаючи ролі користувачів, оновлення токенів (refresh tokens) і додаткові механізми безпеки, такі як обмеження терміну дії сесій.

1 Вподобання