Getting there with Devise MFA
This commit is contained in:
2
Gemfile
2
Gemfile
@@ -7,7 +7,7 @@ ruby "3.3.1"
|
|||||||
gem "rails", "7.1.3.3"
|
gem "rails", "7.1.3.3"
|
||||||
|
|
||||||
gem 'devise'
|
gem 'devise'
|
||||||
gem 'webauthn'
|
gem 'devise-two-factor'
|
||||||
|
|
||||||
# The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
|
# The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
|
||||||
gem "sprockets-rails"
|
gem "sprockets-rails"
|
||||||
|
|||||||
35
Gemfile.lock
35
Gemfile.lock
@@ -77,12 +77,9 @@ GEM
|
|||||||
tzinfo (~> 2.0)
|
tzinfo (~> 2.0)
|
||||||
addressable (2.8.6)
|
addressable (2.8.6)
|
||||||
public_suffix (>= 2.0.2, < 6.0)
|
public_suffix (>= 2.0.2, < 6.0)
|
||||||
android_key_attestation (0.3.0)
|
|
||||||
awrence (1.2.1)
|
|
||||||
base64 (0.2.0)
|
base64 (0.2.0)
|
||||||
bcrypt (3.1.20)
|
bcrypt (3.1.20)
|
||||||
bigdecimal (3.1.8)
|
bigdecimal (3.1.8)
|
||||||
bindata (2.5.0)
|
|
||||||
bindex (0.8.1)
|
bindex (0.8.1)
|
||||||
bootsnap (1.18.3)
|
bootsnap (1.18.3)
|
||||||
msgpack (~> 1.2)
|
msgpack (~> 1.2)
|
||||||
@@ -96,12 +93,8 @@ GEM
|
|||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
regexp_parser (>= 1.5, < 3.0)
|
regexp_parser (>= 1.5, < 3.0)
|
||||||
xpath (~> 3.2)
|
xpath (~> 3.2)
|
||||||
cbor (0.5.9.8)
|
|
||||||
concurrent-ruby (1.2.3)
|
concurrent-ruby (1.2.3)
|
||||||
connection_pool (2.4.1)
|
connection_pool (2.4.1)
|
||||||
cose (1.3.0)
|
|
||||||
cbor (~> 0.5.9)
|
|
||||||
openssl-signature_algorithm (~> 1.0)
|
|
||||||
crass (1.0.6)
|
crass (1.0.6)
|
||||||
date (3.3.4)
|
date (3.3.4)
|
||||||
debug (1.9.2)
|
debug (1.9.2)
|
||||||
@@ -113,6 +106,11 @@ GEM
|
|||||||
railties (>= 4.1.0)
|
railties (>= 4.1.0)
|
||||||
responders
|
responders
|
||||||
warden (~> 1.2.3)
|
warden (~> 1.2.3)
|
||||||
|
devise-two-factor (5.0.0)
|
||||||
|
activesupport (~> 7.0)
|
||||||
|
devise (~> 4.0)
|
||||||
|
railties (~> 7.0)
|
||||||
|
rotp (~> 6.0)
|
||||||
drb (2.2.1)
|
drb (2.2.1)
|
||||||
erubi (1.12.0)
|
erubi (1.12.0)
|
||||||
globalid (1.2.1)
|
globalid (1.2.1)
|
||||||
@@ -130,8 +128,6 @@ GEM
|
|||||||
jbuilder (2.12.0)
|
jbuilder (2.12.0)
|
||||||
actionview (>= 5.0.0)
|
actionview (>= 5.0.0)
|
||||||
activesupport (>= 5.0.0)
|
activesupport (>= 5.0.0)
|
||||||
jwt (2.8.1)
|
|
||||||
base64
|
|
||||||
loofah (2.22.0)
|
loofah (2.22.0)
|
||||||
crass (~> 1.0.2)
|
crass (~> 1.0.2)
|
||||||
nokogiri (>= 1.12.0)
|
nokogiri (>= 1.12.0)
|
||||||
@@ -161,9 +157,6 @@ GEM
|
|||||||
nokogiri (1.16.5)
|
nokogiri (1.16.5)
|
||||||
mini_portile2 (~> 2.8.2)
|
mini_portile2 (~> 2.8.2)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
openssl (3.2.0)
|
|
||||||
openssl-signature_algorithm (1.3.0)
|
|
||||||
openssl (> 2.0)
|
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
psych (5.1.2)
|
psych (5.1.2)
|
||||||
stringio
|
stringio
|
||||||
@@ -218,9 +211,8 @@ GEM
|
|||||||
actionpack (>= 5.2)
|
actionpack (>= 5.2)
|
||||||
railties (>= 5.2)
|
railties (>= 5.2)
|
||||||
rexml (3.2.6)
|
rexml (3.2.6)
|
||||||
|
rotp (6.3.0)
|
||||||
rubyzip (2.3.2)
|
rubyzip (2.3.2)
|
||||||
safety_net_attestation (0.4.0)
|
|
||||||
jwt (~> 2.0)
|
|
||||||
selenium-webdriver (4.20.1)
|
selenium-webdriver (4.20.1)
|
||||||
base64 (~> 0.2)
|
base64 (~> 0.2)
|
||||||
rexml (~> 3.2, >= 3.2.5)
|
rexml (~> 3.2, >= 3.2.5)
|
||||||
@@ -238,10 +230,6 @@ GEM
|
|||||||
stringio (3.1.0)
|
stringio (3.1.0)
|
||||||
thor (1.3.1)
|
thor (1.3.1)
|
||||||
timeout (0.4.1)
|
timeout (0.4.1)
|
||||||
tpm-key_attestation (0.12.0)
|
|
||||||
bindata (~> 2.4)
|
|
||||||
openssl (> 2.0)
|
|
||||||
openssl-signature_algorithm (~> 1.0)
|
|
||||||
turbo-rails (2.0.5)
|
turbo-rails (2.0.5)
|
||||||
actionpack (>= 6.0.0)
|
actionpack (>= 6.0.0)
|
||||||
activejob (>= 6.0.0)
|
activejob (>= 6.0.0)
|
||||||
@@ -255,15 +243,6 @@ GEM
|
|||||||
activemodel (>= 6.0.0)
|
activemodel (>= 6.0.0)
|
||||||
bindex (>= 0.4.0)
|
bindex (>= 0.4.0)
|
||||||
railties (>= 6.0.0)
|
railties (>= 6.0.0)
|
||||||
webauthn (3.1.0)
|
|
||||||
android_key_attestation (~> 0.3.0)
|
|
||||||
awrence (~> 1.1)
|
|
||||||
bindata (~> 2.4)
|
|
||||||
cbor (~> 0.5.9)
|
|
||||||
cose (~> 1.1)
|
|
||||||
openssl (>= 2.2)
|
|
||||||
safety_net_attestation (~> 0.4.0)
|
|
||||||
tpm-key_attestation (~> 0.12.0)
|
|
||||||
webrick (1.8.1)
|
webrick (1.8.1)
|
||||||
websocket (1.2.10)
|
websocket (1.2.10)
|
||||||
websocket-driver (0.7.6)
|
websocket-driver (0.7.6)
|
||||||
@@ -281,6 +260,7 @@ DEPENDENCIES
|
|||||||
capybara
|
capybara
|
||||||
debug
|
debug
|
||||||
devise
|
devise
|
||||||
|
devise-two-factor
|
||||||
importmap-rails
|
importmap-rails
|
||||||
jbuilder
|
jbuilder
|
||||||
mysql2 (~> 0.5)
|
mysql2 (~> 0.5)
|
||||||
@@ -292,7 +272,6 @@ DEPENDENCIES
|
|||||||
turbo-rails
|
turbo-rails
|
||||||
tzinfo-data
|
tzinfo-data
|
||||||
web-console
|
web-console
|
||||||
webauthn
|
|
||||||
|
|
||||||
RUBY VERSION
|
RUBY VERSION
|
||||||
ruby 3.3.1p55
|
ruby 3.3.1p55
|
||||||
|
|||||||
@@ -1,3 +1,10 @@
|
|||||||
class ApplicationController < ActionController::Base
|
class ApplicationController < ActionController::Base
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
|
before_action :configure_permitted_parameters, if: :devise_controller?
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def configure_permitted_parameters
|
||||||
|
devise_parameter_sanitizer.permit(:sign_in, keys: [:otp_attempt])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
class User < ApplicationRecord
|
class User < ApplicationRecord
|
||||||
|
devise :two_factor_authenticatable
|
||||||
# Include default devise modules. Others available are:
|
# Include default devise modules. Others available are:
|
||||||
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
|
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
|
||||||
devise :database_authenticatable, :recoverable, :rememberable, :validatable, :lockable, :timeoutable, :trackable, :registerable
|
devise :recoverable, :rememberable, :validatable, :lockable, :timeoutable, :trackable, :registerable
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
RYdwaEGe4bkkqfzKaJgRzzktgKS227tgbhMhGS1aSa69LRZauHIiIBnqQSOSNrRftPa65+QkuSTToq7VvQklLwUPDluIXOudx/IxCjvnmjoVdkBDPFzCIJhM01eD4ZKje6cqTIMQqVCAlZ0dCHuOrdLaU4TiH9qqKN9KqoKfrV9O8IXVV0x7xt8um1KDyT7XQ/JQS6ggmSbiqvkNhwuflgrYJFzMfX4/glcCTSviFzhW0ri4XOA6LYnQhYF6ed8z/mNaiVM1Q2yBspVNIxCFwQEs8kF/VWmVjSUdPFExR3Tt0j/w7zc4e9LlxbHvPcJg43f6de3Wn2pJ8DQbc3HB8Lg29ENKqwSSoMwzQUfL6LP96pClZ4vz7XsjApMtYHINH/fxeplNAyfS9bniTmWw3z78mXI2OBK1cxH5--Hxh1AHoj2eUcIPCJ--MDVZpDlIQA0rY04Lx86jsg==
|
16XC4dR/e6ZfMDLdM5A1IWRXPbWK5XG6e3/4HXV5cKxtkL/tYSfw+JduP8XpJtH0+paiRcQ+KZvLNndy+U+K/u9GkimSKGC1u/3iIreWGH44NW5G6DpG02kqa+7F27Vt0vyK0LKG+eipwuusUi5lxlVYWV1NoxCyEgDhh0oylMBZTs5eiD82CUpXcOOi/Y6WII3XfmCa0JTn1FvMKtX8HKWUMzCJXowBhZ9MkPpjEENzBPVn5N0MbWsuwTygcABE0KyuCISpwCUrIuNFnQLhNoPAApo2MD1sAiPjDb/xVV9rwSiSqTzaovjkXadGnhDa+7gh5LRTqgpn5yuBm19ud9JVTflVomXQooHrByJEMRSWJ1BsLro7R+3eEqCsHtbgLjQ0Vpa+moO4XTvzdMOtpZvpMjY3zlHatWCEsjBXVZaTL2ptmfXjVjXscZOge6Jomw8+VjAJaAPSnR8l+O+pTu3n4oCQ270YIZhGDk+3m2zUkqb8uHDy/0pulMUSFUSI6UV7A46V061H17bnAERzHIQiFQkBLbmFWEvsPG6mMi6J7J7ynRc5/6avrj+9mKr6/REWwQijJwQTRMsSlzTaGQY6ecUX4lDxS3kzVxccqYophPR9tAwOwxjfTWyrLtQPdTPaGkh6rUcQO36BF5A=--vGTJqJldqOOCgx5I--NEnAbiMfebeJNQd9LIBAOg==
|
||||||
@@ -9,6 +9,10 @@
|
|||||||
# Use this hook to configure devise mailer, warden hooks and so forth.
|
# Use this hook to configure devise mailer, warden hooks and so forth.
|
||||||
# Many of these configuration options can be set straight in your model.
|
# Many of these configuration options can be set straight in your model.
|
||||||
Devise.setup do |config|
|
Devise.setup do |config|
|
||||||
|
config.warden do |manager|
|
||||||
|
manager.default_strategies(:scope => :user).unshift :two_factor_authenticatable
|
||||||
|
end
|
||||||
|
|
||||||
# The secret key used by Devise. Devise uses this key to generate
|
# The secret key used by Devise. Devise uses this key to generate
|
||||||
# random tokens. Changing this key will render invalid all existing
|
# random tokens. Changing this key will render invalid all existing
|
||||||
# confirmation, reset password and unlock tokens in the database.
|
# confirmation, reset password and unlock tokens in the database.
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
WebAuthn.configure do |config|
|
|
||||||
# This value needs to match `window.location.origin` evaluated by
|
|
||||||
# the User Agent during registration and authentication ceremonies.
|
|
||||||
config.origin = "https://mailadmin.hiddenagenda.ltd.uk"
|
|
||||||
|
|
||||||
# Relying Party name for display purposes
|
|
||||||
config.rp_name = "Hidden Agenda Ltd"
|
|
||||||
|
|
||||||
# Optionally configure a client timeout hint, in milliseconds.
|
|
||||||
# This hint specifies how long the browser should wait for any
|
|
||||||
# interaction with the user.
|
|
||||||
# This hint may be overridden by the browser.
|
|
||||||
# https://www.w3.org/TR/webauthn/#dom-publickeycredentialcreationoptions-timeout
|
|
||||||
# config.credential_options_timeout = 120_000
|
|
||||||
|
|
||||||
# You can optionally specify a different Relying Party ID
|
|
||||||
# (https://www.w3.org/TR/webauthn/#relying-party-identifier)
|
|
||||||
# if it differs from the default one.
|
|
||||||
#
|
|
||||||
# In this case the default would be "auth.example.com", but you can set it to
|
|
||||||
# the suffix "example.com"
|
|
||||||
#
|
|
||||||
# config.rp_id = "example.com"
|
|
||||||
|
|
||||||
# Configure preferred binary-to-text encoding scheme. This should match the encoding scheme
|
|
||||||
# used in your client-side (user agent) code before sending the credential to the server.
|
|
||||||
# Supported values: `:base64url` (default), `:base64` or `false` to disable all encoding.
|
|
||||||
#
|
|
||||||
# config.encoding = :base64url
|
|
||||||
|
|
||||||
# Possible values: "ES256", "ES384", "ES512", "PS256", "PS384", "PS512", "RS256", "RS384", "RS512", "RS1"
|
|
||||||
# Default: ["ES256", "PS256", "RS256"]
|
|
||||||
#
|
|
||||||
# config.algorithms << "ES384"
|
|
||||||
end
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
class AddDomainIdToVirtuals < ActiveRecord::Migration[7.0]
|
|
||||||
def change
|
|
||||||
add_column :virtuals, :domain_id, :integer
|
|
||||||
add_column :credentials, :domain_id, :integer
|
|
||||||
add_index :virtuals, :domain_id
|
|
||||||
add_index :credentials, :domain_id
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class AddDeviseTwoFactorToUsers < ActiveRecord::Migration[7.1]
|
||||||
|
def change
|
||||||
|
add_column :users, :otp_secret, :string
|
||||||
|
add_column :users, :consumed_timestep, :integer
|
||||||
|
add_column :users, :otp_required_for_login, :boolean
|
||||||
|
end
|
||||||
|
end
|
||||||
6
db/schema.rb
generated
6
db/schema.rb
generated
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[7.0].define(version: 2023_06_21_060115) do
|
ActiveRecord::Schema[7.1].define(version: 2024_05_21_090545) do
|
||||||
create_table "credentials", charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
|
create_table "credentials", charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
|
||||||
t.string "email"
|
t.string "email"
|
||||||
t.string "password"
|
t.string "password"
|
||||||
@@ -42,6 +42,10 @@ ActiveRecord::Schema[7.0].define(version: 2023_06_21_060115) do
|
|||||||
t.datetime "locked_at"
|
t.datetime "locked_at"
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
|
t.string "webauthn_id"
|
||||||
|
t.string "otp_secret"
|
||||||
|
t.integer "consumed_timestep"
|
||||||
|
t.boolean "otp_required_for_login"
|
||||||
t.index ["email"], name: "index_users_on_email", unique: true
|
t.index ["email"], name: "index_users_on_email", unique: true
|
||||||
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
|
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
|
||||||
t.index ["unlock_token"], name: "index_users_on_unlock_token", unique: true
|
t.index ["unlock_token"], name: "index_users_on_unlock_token", unique: true
|
||||||
|
|||||||
Reference in New Issue
Block a user