Двухфакторная аутентификация с Рубином (посредством разработки)


Я собираюсь добавить два фактора аутентификации для моего приложения Ruby. Мне нужна действительно простая реализация его с простыми случаями использования:

  • Возможность генерировать и отправлять коды по sms или электронной почте (значит, я не хочу быть прикрепленным к Google Authenticator с этим);

  • Возможность показать сначала форму логин-пароль, а затем форму для кода (так же, как это делает сейчас github).

Пока не похоже на ракетостроение. Но почему-то я застрял.

Итак, мой вопрос в следующем: пытался ли кто-нибудь реализовать это, и если да, то какую стратегию вы использовали для этого?


Я пробовал использовать devise-two-factor драгоценный камень, который описывается как "двухфакторная аутентификация Barebones с Devise".

Под капотом он аутентифицирует пользователя с помощью логина + пароля+кода (все одновременно). Но в моем случае я хочу, чтобы пользователь сначала ввел логин+пароль (с помощью формы posting), а затем отправил код пользователю, прежде чем пользователь затем введет код позже, на следующее окно.

Единственное решение, которое я нашел, - это хранить логин и пароль в сеансе (sic!) и использовать для аутентификации пользователя после того, как он ввел 2-факторный код. Я не слишком уверен в этой стратегии.

3 3

3 ответа:

Devise-two-factor-это мнение о том, как должен работать Ваш логин. Я думаю, что вам лучше использоватьROTP gem напрямую (который использует devise-two-factor) и реализовать пользовательское решение.

Рики у Twilio здесь.

Мы построили приложение для двухфакторной аутентификации в Ruby, которое вы можете проверить, если ищете вдохновение. Наше приложение использует Authy, и есть пара связанных битов в коде, чтобы начать это.

Во-первых, при создании нового пользователя необходимо зарегистрировать его в Authy, чтобы включить 2FA:

    @user = User.new(user_params)
    if @user.save
      session[:user_id] = @user.id

      authy = Authy::API.register_user(
        email: @user.email,
        cellphone: @user.phone_number,
        country_code: @user.country_code
      )
      @user.update(authy_id: authy.id)

      redirect_to account_path
    else
      render :new
    end

Затем, когда пользователь пытается войти в систему, Вы можете использовать Authy для отправки токена через SMS, а затем проверить токен, который они введите:

  def send_token
    @user = User.find(session[:pre_2fa_auth_user_id])
    Authy::API.request_sms(id: @user.authy_id)
    render plain: 'sending token'
  end

  def verify
    @user = User.find(session[:pre_2fa_auth_user_id])
    token = Authy::API.verify(id: @user.authy_id, token: params[:token])
    if token.ok?
      session[:user_id] = @user.id
      session[:pre_2fa_auth_user_id] = nil
      redirect_to account_path
    else
      flash.now[:danger] = "Incorrect code, please try again"
      redirect_to new_session_path
    end
  end

Надеюсь, это поможет!

Кажется, что здесь лучше ответить самому себе: в конце концов, я обнаружил, что способ GitLab делать это 2FA больше всего соответствует моим потребностям: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/474

Поэтому я использую некоторые идеи из этого кода.

Спасибо вам, ребята из gitlab, вы мне очень помогли!