Commit e55e0c5

mo <mo.khan@gmail.com>
2018-09-03 22:22:55
validate mfa code.
1 parent bbf59b7
Changed files (4)
app
config
spec
app/controllers/mfas_controller.rb
@@ -1,4 +1,18 @@
 class MfasController < ApplicationController
   def new
   end
+
+  def create
+    if current_user.tfa.authenticate(secure_params[:code])
+      redirect_to response_path
+    else
+      redirect_to mfa_path, error: "Invalid code"
+    end
+  end
+
+  private
+
+  def secure_params
+    params.require(:mfa).permit(:code)
+  end
 end
app/models/tfa.rb
@@ -12,7 +12,6 @@ class Tfa
   end
 
   def provisioning_uri
-    totp = ::ROTP::TOTP.new(secret, issuer: 'saml-kit')
     totp.provisioning_uri(user.email)
   end
 
@@ -29,6 +28,16 @@ class Tfa
   end
 
   def current_totp
-    ROTP::TOTP.new(secret).now
+    totp.now
+  end
+
+  def authenticate(entered_code)
+    totp.verify(entered_code)
+  end
+
+  private
+
+  def totp
+    @totp ||= ::ROTP::TOTP.new(secret, issuer: 'saml-kit')
   end
 end
config/routes.rb
@@ -4,6 +4,7 @@ Rails.application.routes.draw do
   post "/session/new" => "sessions#new"
   resource :metadata, only: [:show]
   resource :mfa, only: [:new, :create]
+  resource :response, only: [:show]
   resource :session, only: [:new, :create, :destroy]
   resources :registrations, only: [:new, :create]
 
spec/requests/mfas_spec.rb
@@ -11,6 +11,23 @@ RSpec.describe "/mfa" do
 
       specify { expect(response).to have_http_status(:ok) }
     end
+
+    describe "POST /mfa" do
+      context "when the code is correct" do
+        let(:correct_code) { current_user.tfa.current_totp }
+        before { post '/mfa', params: { mfa: { code: correct_code } } }
+
+        specify { expect(response).to redirect_to(response_path) }
+      end
+
+      context "when the code is incorrect" do
+        let(:incorrect_code) { rand(1_000) }
+        before { post '/mfa', params: { mfa: { code: incorrect_code } } }
+
+        specify { expect(response).to redirect_to(mfa_path) }
+        specify { expect(flash[:error]).to be_present }
+      end
+    end
   end
 
   context "when username/password entry has not been completed" do