authentication-zero 2.16.4 → 2.16.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/Gemfile.lock +1 -1
- data/README.md +8 -8
- data/lib/authentication_zero/version.rb +1 -1
- data/lib/generators/authentication/authentication_generator.rb +16 -7
- data/lib/generators/authentication/templates/controllers/api/application_controller.rb.tt +0 -7
- data/lib/generators/authentication/templates/controllers/api/identity/emails_controller.rb.tt +3 -4
- data/lib/generators/authentication/templates/controllers/api/identity/password_resets_controller.rb.tt +6 -2
- data/lib/generators/authentication/templates/controllers/html/application_controller.rb.tt +0 -11
- data/lib/generators/authentication/templates/controllers/html/identity/email_verifications_controller.rb.tt +5 -1
- data/lib/generators/authentication/templates/controllers/html/identity/emails_controller.rb.tt +3 -4
- data/lib/generators/authentication/templates/controllers/html/identity/password_resets_controller.rb.tt +11 -3
- data/lib/generators/authentication/templates/controllers/html/sessions/passwordlesses_controller.rb.tt +42 -0
- data/lib/generators/authentication/templates/controllers/html/sessions_controller.rb.tt +0 -1
- data/lib/generators/authentication/templates/controllers/html/two_factor_authentication/totps_controller.rb.tt +3 -4
- data/lib/generators/authentication/templates/erb/identity/emails/edit.html.erb.tt +6 -1
- data/lib/generators/authentication/templates/erb/identity/password_resets/new.html.erb.tt +1 -1
- data/lib/generators/authentication/templates/erb/registrations/new.html.erb.tt +1 -1
- data/lib/generators/authentication/templates/erb/sessions/new.html.erb.tt +9 -1
- data/lib/generators/authentication/templates/erb/sessions/passwordlesses/new.html.erb.tt +14 -0
- data/lib/generators/authentication/templates/erb/two_factor_authentication/totps/new.html.erb.tt +6 -1
- data/lib/generators/authentication/templates/erb/user_mailer/passwordless.html.erb.tt +9 -0
- data/lib/generators/authentication/templates/mailers/user_mailer.rb.tt +8 -0
- data/lib/generators/authentication/templates/migrations/create_sign_in_tokens_migration.rb.tt +7 -0
- data/lib/generators/authentication/templates/models/session.rb.tt +0 -8
- data/lib/generators/authentication/templates/models/sign_in_token.rb.tt +3 -0
- data/lib/generators/authentication/templates/models/user.rb.tt +6 -3
- data/lib/generators/authentication/templates/test_unit/controllers/api/identity/emails_controller_test.rb.tt +8 -1
- data/lib/generators/authentication/templates/test_unit/controllers/html/identity/emails_controller_test.rb.tt +8 -1
- data/lib/generators/authentication/templates/test_unit/system/identity/emails_test.rb.tt +1 -0
- metadata +7 -5
- data/lib/generators/authentication/templates/controllers/api/sessions/sudos_controller.rb.tt +0 -11
- data/lib/generators/authentication/templates/controllers/html/sessions/sudos_controller.rb.tt +0 -14
- data/lib/generators/authentication/templates/erb/sessions/sudos/new.html.erb.tt +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d512c515587bc57bb47c2f89b27eea08f96a74c440bb0d404756613fa0cdbec5
|
4
|
+
data.tar.gz: 7b9781caa350fe751d9b2799d186b73a563bc4d108051b9a9491b09a45bb6e9e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e0c90d112f6187a644841f3e394c9435eb9e9b9faf96109b29b16a96443ffeda5f3f375d8ba9b987742288807dab06e79a156f5b0a70d1794d81242a4f44c25
|
7
|
+
data.tar.gz: 8b79ad8fcc211053fe15ffcabac6ffd7033c7d1d093d715bf5cb6ceffbf595718f7f85d14b94e90d8170bb78c676a6890e4c0a76b3707034252073c580af6fac
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
## Authentication Zero 2.16.6 ##
|
2
|
+
|
3
|
+
* Remove passwordless from api template
|
4
|
+
* Remove sudoable, I want to make things simple for new users,
|
5
|
+
and it will became even simpler with the new rails 7.1 "password challenge api"
|
6
|
+
|
7
|
+
## Authentication Zero 2.16.5 ##
|
8
|
+
|
9
|
+
* Revoke all password reset tokens (security enhancement)
|
10
|
+
* Sign in without password (new feature)
|
11
|
+
|
1
12
|
## Authentication Zero 2.16.4 (February 11, 2023) ##
|
2
13
|
|
3
14
|
* Increase attemps for lockable sign-in
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -27,11 +27,11 @@ Since Authentication Zero generates this code into your application instead of b
|
|
27
27
|
- Checks if a password has been found in any data breach (--pwned)
|
28
28
|
- Authentication by cookie
|
29
29
|
- Authentication by token (--api)
|
30
|
+
- Passwordless authentication (--passwordless)
|
30
31
|
- Two factor authentication (--two-factor)
|
31
32
|
- Social Login with OmniAuth (--omniauthable)
|
32
33
|
- Verify email using a link with token
|
33
34
|
- Verify email using a six random digits code for api (--code-verifiable)
|
34
|
-
- Ask password before sensitive data changes, aka: sudo (--sudoable)
|
35
35
|
- Reset the user password and send reset instructions
|
36
36
|
- Reset the user password only from verified emails
|
37
37
|
- Lock mechanism for resetting password and sign-in (--lockable)
|
@@ -41,17 +41,17 @@ Since Authentication Zero generates this code into your application instead of b
|
|
41
41
|
- Activity log (--trackable)
|
42
42
|
- Log out
|
43
43
|
|
44
|
-
##
|
44
|
+
## Generated code
|
45
45
|
|
46
|
-
- [has_secure_password](https://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html#method-i-has_secure_password): Adds methods to set and authenticate against a
|
46
|
+
- [has_secure_password](https://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html#method-i-has_secure_password): Adds methods to set and authenticate against a bcrypt password.
|
47
47
|
- [signed cookies](https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html): Returns a jar that'll automatically generate a signed representation of cookie value and verify it when reading from the cookie again.
|
48
48
|
- [httponly cookies](https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html): A cookie with the httponly attribute is inaccessible to the JavaScript, this precaution helps mitigate cross-site scripting (XSS) attacks.
|
49
49
|
- [signed_id](https://api.rubyonrails.org/classes/ActiveRecord/SignedId.html): Returns a signed id that is tamper proof, so it's safe to send in an email or otherwise share with the outside world.
|
50
|
-
- [
|
51
|
-
- [
|
52
|
-
- [
|
53
|
-
- [
|
54
|
-
- [
|
50
|
+
- [current attributes](https://api.rubyonrails.org/classes/ActiveSupport/CurrentAttributes.html): Abstract super class that provides a thread-isolated attributes singleton, which resets automatically before and after each request.
|
51
|
+
- [action mailer](https://api.rubyonrails.org/classes/ActionMailer/Base.html): Action Mailer allows you to send email from your application using a mailer model and views.
|
52
|
+
- [log filtering](https://guides.rubyonrails.org/action_controller_overview.html#log-filtering): Parameters 'token' and 'password' are marked [FILTERED] in the log.
|
53
|
+
- [functional tests](https://guides.rubyonrails.org/testing.html#functional-tests-for-your-controllers): In Rails, testing the various actions of a controller is a form of writing functional tests.
|
54
|
+
- [system testing](https://guides.rubyonrails.org/testing.html#system-testing): System tests allow you to test user interactions with your application, running tests in either a real or a headless browser.
|
55
55
|
|
56
56
|
## Development
|
57
57
|
|
@@ -6,8 +6,8 @@ class AuthenticationGenerator < Rails::Generators::Base
|
|
6
6
|
class_option :api, type: :boolean, desc: "Generates API authentication"
|
7
7
|
class_option :pwned, type: :boolean, desc: "Add pwned password validation"
|
8
8
|
class_option :code_verifiable, type: :boolean, desc: "Add email verification using a code for api"
|
9
|
-
class_option :sudoable, type: :boolean, desc: "Add password request before sensitive data changes"
|
10
9
|
class_option :lockable, type: :boolean, desc: "Add password reset locking"
|
10
|
+
class_option :passwordless, type: :boolean, desc: "Add passwordless sign"
|
11
11
|
class_option :omniauthable, type: :boolean, desc: "Add social login support"
|
12
12
|
class_option :trackable, type: :boolean, desc: "Add activity log support"
|
13
13
|
class_option :two_factor, type: :boolean, desc: "Add two factor authentication"
|
@@ -52,6 +52,7 @@ class AuthenticationGenerator < Rails::Generators::Base
|
|
52
52
|
migration_template "migrations/create_sessions_migration.rb", "#{db_migrate_path}/create_sessions.rb"
|
53
53
|
migration_template "migrations/create_email_verification_tokens_migration.rb", "#{db_migrate_path}/create_email_verification_tokens.rb"
|
54
54
|
migration_template "migrations/create_password_reset_tokens_migration.rb", "#{db_migrate_path}/create_password_reset_tokens.rb"
|
55
|
+
migration_template "migrations/create_sign_in_tokens_migration.rb", "#{db_migrate_path}/create_sign_in_tokens_migration.rb" if passwordless?
|
55
56
|
migration_template "migrations/create_events_migration.rb", "#{db_migrate_path}/create_events.rb" if options.trackable?
|
56
57
|
end
|
57
58
|
|
@@ -60,6 +61,7 @@ class AuthenticationGenerator < Rails::Generators::Base
|
|
60
61
|
template "models/session.rb", "app/models/session.rb"
|
61
62
|
template "models/email_verification_token.rb", "app/models/email_verification_token.rb"
|
62
63
|
template "models/password_reset_token.rb", "app/models/password_reset_token.rb"
|
64
|
+
template "models/sign_in_token.rb", "app/models/sign_in_token.rb" if passwordless?
|
63
65
|
template "models/current.rb", "app/models/current.rb"
|
64
66
|
template "models/event.rb", "app/models/event.rb" if options.trackable?
|
65
67
|
end
|
@@ -77,8 +79,8 @@ class AuthenticationGenerator < Rails::Generators::Base
|
|
77
79
|
template "controllers/#{format_folder}/passwords_controller.rb", "app/controllers/passwords_controller.rb"
|
78
80
|
template "controllers/#{format_folder}/registrations_controller.rb", "app/controllers/registrations_controller.rb"
|
79
81
|
template "controllers/#{format_folder}/home_controller.rb", "app/controllers/home_controller.rb" unless options.api?
|
80
|
-
template "controllers/#{format_folder}/sessions/sudos_controller.rb", "app/controllers/sessions/sudos_controller.rb" if options.sudoable?
|
81
82
|
template "controllers/#{format_folder}/sessions/omniauth_controller.rb", "app/controllers/sessions/omniauth_controller.rb" if omniauthable?
|
83
|
+
template "controllers/#{format_folder}/sessions/passwordlesses_controller.rb", "app/controllers/sessions/passwordlesses_controller.rb" if passwordless?
|
82
84
|
template "controllers/#{format_folder}/authentications/events_controller.rb", "app/controllers/authentications/events_controller.rb" if options.trackable?
|
83
85
|
end
|
84
86
|
|
@@ -96,10 +98,10 @@ class AuthenticationGenerator < Rails::Generators::Base
|
|
96
98
|
directory "erb/passwords", "app/views/passwords"
|
97
99
|
directory "erb/registrations", "app/views/registrations"
|
98
100
|
|
99
|
-
template
|
100
|
-
template
|
101
|
+
template "erb/sessions/index.html.erb", "app/views/sessions/index.html.erb"
|
102
|
+
template "erb/sessions/new.html.erb", "app/views/sessions/new.html.erb"
|
101
103
|
|
102
|
-
directory "erb/sessions/
|
104
|
+
directory "erb/sessions/passwordlesses", "app/views/sessions/passwordlesses" if passwordless?
|
103
105
|
|
104
106
|
directory "erb/two_factor_authentication", "app/views/two_factor_authentication" if two_factor?
|
105
107
|
directory "erb/authentications/events", "app/views/authentications/events" if options.trackable?
|
@@ -113,6 +115,10 @@ class AuthenticationGenerator < Rails::Generators::Base
|
|
113
115
|
def add_routes
|
114
116
|
route "root 'home#index'" unless options.api?
|
115
117
|
|
118
|
+
if passwordless?
|
119
|
+
route "resource :passwordless, only: [:new, :edit, :create]", namespace: :sessions
|
120
|
+
end
|
121
|
+
|
116
122
|
if omniauthable?
|
117
123
|
route "post '/auth/:provider/callback', to: 'sessions/omniauth#create'"
|
118
124
|
route "get '/auth/:provider/callback', to: 'sessions/omniauth#create'"
|
@@ -131,7 +137,6 @@ class AuthenticationGenerator < Rails::Generators::Base
|
|
131
137
|
route "resource :password_reset, only: [:new, :edit, :create, :update]", namespace: :identity
|
132
138
|
route "resource :email_verification, only: [:edit, :create]", namespace: :identity
|
133
139
|
route "resource :email, only: [:edit, :update]", namespace: :identity
|
134
|
-
route "resource :sudo, only: [:new, :create]", namespace: :sessions if options.sudoable?
|
135
140
|
route "resource :password, only: [:edit, :update]"
|
136
141
|
route "resources :sessions, only: [:index, :show, :destroy]"
|
137
142
|
route "post 'sign_up', to: 'registrations#create'"
|
@@ -157,6 +162,10 @@ class AuthenticationGenerator < Rails::Generators::Base
|
|
157
162
|
options.omniauthable? && !options.api?
|
158
163
|
end
|
159
164
|
|
165
|
+
def passwordless?
|
166
|
+
options.passwordless? && !options.api?
|
167
|
+
end
|
168
|
+
|
160
169
|
def two_factor?
|
161
170
|
options.two_factor? && !options.api?
|
162
171
|
end
|
@@ -166,6 +175,6 @@ class AuthenticationGenerator < Rails::Generators::Base
|
|
166
175
|
end
|
167
176
|
|
168
177
|
def redis?
|
169
|
-
options.lockable? ||
|
178
|
+
options.lockable? || code_verifiable?
|
170
179
|
end
|
171
180
|
end
|
@@ -3,13 +3,6 @@ class ApplicationController < ActionController::API
|
|
3
3
|
|
4
4
|
before_action :set_current_request_details
|
5
5
|
before_action :authenticate
|
6
|
-
<%- if options.sudoable? %>
|
7
|
-
def require_sudo
|
8
|
-
unless Current.session.sudo?
|
9
|
-
render json: { error: "Enter your password to continue" }, status: :forbidden
|
10
|
-
end
|
11
|
-
end
|
12
|
-
<%- end -%>
|
13
6
|
<%- if options.lockable? %>
|
14
7
|
def require_lock(wait: 1.hour, attempts: 10)
|
15
8
|
counter = Kredis.counter("require_lock:#{request.remote_ip}:#{params[:controller]}:#{params[:action]}", expires_in: wait)
|
data/lib/generators/authentication/templates/controllers/api/identity/emails_controller.rb.tt
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
class Identity::EmailsController < ApplicationController
|
2
|
-
<%- if options.sudoable? -%>
|
3
|
-
before_action :require_sudo
|
4
|
-
<%- end -%>
|
5
2
|
before_action :set_user
|
6
3
|
|
7
4
|
def update
|
8
|
-
|
5
|
+
if !@user.authenticate(params[:current_password])
|
6
|
+
render json: { error: "The password you entered is incorrect" }, status: :bad_request
|
7
|
+
elsif @user.update(user_params)
|
9
8
|
render_show
|
10
9
|
else
|
11
10
|
render json: @user.errors, status: :unprocessable_entity
|
@@ -1,10 +1,10 @@
|
|
1
1
|
class Identity::PasswordResetsController < ApplicationController
|
2
2
|
skip_before_action :authenticate
|
3
3
|
|
4
|
-
before_action :set_user, only: :update
|
5
4
|
<%- if options.lockable? -%>
|
6
5
|
before_action :require_lock, only: :create
|
7
6
|
<%- end -%>
|
7
|
+
before_action :set_user, only: :update
|
8
8
|
|
9
9
|
def create
|
10
10
|
if @user = User.find_by(email: params[:email], verified: true)
|
@@ -16,7 +16,7 @@ class Identity::PasswordResetsController < ApplicationController
|
|
16
16
|
|
17
17
|
def update
|
18
18
|
if @user.update(user_params)
|
19
|
-
|
19
|
+
revoke_tokens; render(json: @user)
|
20
20
|
else
|
21
21
|
render json: @user.errors, status: :unprocessable_entity
|
22
22
|
end
|
@@ -32,4 +32,8 @@ class Identity::PasswordResetsController < ApplicationController
|
|
32
32
|
def user_params
|
33
33
|
params.permit(:password, :password_confirmation)
|
34
34
|
end
|
35
|
+
|
36
|
+
def revoke_tokens
|
37
|
+
@user.password_reset_tokens.delete_all
|
38
|
+
end
|
35
39
|
end
|
@@ -1,17 +1,6 @@
|
|
1
1
|
class ApplicationController < ActionController::Base
|
2
2
|
before_action :set_current_request_details
|
3
3
|
before_action :authenticate
|
4
|
-
<%- if options.sudoable? %>
|
5
|
-
def require_sudo
|
6
|
-
<%- if omniauthable? -%>
|
7
|
-
unless Current.session.sudo? || Current.session.user.provider.present?
|
8
|
-
<%- else -%>
|
9
|
-
unless Current.session.sudo?
|
10
|
-
<%- end -%>
|
11
|
-
redirect_to new_sessions_sudo_path(proceed_to_url: request.url)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
<%- end -%>
|
15
4
|
<%- if options.lockable? %>
|
16
5
|
def require_lock(wait: 1.hour, attempts: 10)
|
17
6
|
counter = Kredis.counter("require_lock:#{request.remote_ip}:#{params[:controller]}:#{params[:action]}", expires_in: wait)
|
@@ -9,7 +9,7 @@ class Identity::EmailVerificationsController < ApplicationController
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def create
|
12
|
-
|
12
|
+
send_email_verification
|
13
13
|
redirect_to root_path, notice: "We sent a verification email to your email address"
|
14
14
|
end
|
15
15
|
|
@@ -19,4 +19,8 @@ class Identity::EmailVerificationsController < ApplicationController
|
|
19
19
|
rescue
|
20
20
|
redirect_to edit_identity_email_path, alert: "That email verification link is invalid"
|
21
21
|
end
|
22
|
+
|
23
|
+
def send_email_verification
|
24
|
+
UserMailer.with(user: Current.user).email_verification.deliver_later
|
25
|
+
end
|
22
26
|
end
|
data/lib/generators/authentication/templates/controllers/html/identity/emails_controller.rb.tt
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
class Identity::EmailsController < ApplicationController
|
2
|
-
<%- if options.sudoable? -%>
|
3
|
-
before_action :require_sudo
|
4
|
-
<%- end -%>
|
5
2
|
before_action :set_user
|
6
3
|
|
7
4
|
def edit
|
8
5
|
end
|
9
6
|
|
10
7
|
def update
|
11
|
-
|
8
|
+
if !@user.authenticate(params[:current_password])
|
9
|
+
redirect_to edit_identity_email_path, alert: "The password you entered is incorrect"
|
10
|
+
elsif @user.update(user_params)
|
12
11
|
redirect_to_root
|
13
12
|
else
|
14
13
|
render :edit, status: :unprocessable_entity
|
@@ -1,10 +1,10 @@
|
|
1
1
|
class Identity::PasswordResetsController < ApplicationController
|
2
2
|
skip_before_action :authenticate
|
3
3
|
|
4
|
-
before_action :set_user, only: %i[ edit update ]
|
5
4
|
<%- if options.lockable? -%>
|
6
5
|
before_action :require_lock, only: :create
|
7
6
|
<%- end -%>
|
7
|
+
before_action :set_user, only: %i[ edit update ]
|
8
8
|
|
9
9
|
def new
|
10
10
|
end
|
@@ -14,7 +14,7 @@ class Identity::PasswordResetsController < ApplicationController
|
|
14
14
|
|
15
15
|
def create
|
16
16
|
if @user = User.find_by(email: params[:email], verified: true)
|
17
|
-
|
17
|
+
send_password_reset_email
|
18
18
|
redirect_to sign_in_path, notice: "Check your email for reset instructions"
|
19
19
|
else
|
20
20
|
redirect_to new_identity_password_reset_path, alert: "You can't reset your password until you verify your email"
|
@@ -23,7 +23,7 @@ class Identity::PasswordResetsController < ApplicationController
|
|
23
23
|
|
24
24
|
def update
|
25
25
|
if @user.update(user_params)
|
26
|
-
|
26
|
+
revoke_tokens; redirect_to(sign_in_path, notice: "Your password was reset successfully. Please sign in")
|
27
27
|
else
|
28
28
|
render :edit, status: :unprocessable_entity
|
29
29
|
end
|
@@ -39,4 +39,12 @@ class Identity::PasswordResetsController < ApplicationController
|
|
39
39
|
def user_params
|
40
40
|
params.permit(:password, :password_confirmation)
|
41
41
|
end
|
42
|
+
|
43
|
+
def send_password_reset_email
|
44
|
+
UserMailer.with(user: @user).password_reset.deliver_later
|
45
|
+
end
|
46
|
+
|
47
|
+
def revoke_tokens
|
48
|
+
@user.password_reset_tokens.delete_all
|
49
|
+
end
|
42
50
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Sessions::PasswordlessesController < ApplicationController
|
2
|
+
skip_before_action :authenticate
|
3
|
+
|
4
|
+
<%- if options.lockable? -%>
|
5
|
+
before_action :require_lock, only: :create
|
6
|
+
<%- end -%>
|
7
|
+
before_action :set_user, only: :edit
|
8
|
+
|
9
|
+
def new
|
10
|
+
end
|
11
|
+
|
12
|
+
def edit
|
13
|
+
@session = @user.sessions.create!
|
14
|
+
cookies.signed.permanent[:session_token] = { value: @session.id, httponly: true }
|
15
|
+
|
16
|
+
revoke_tokens; redirect_to(root_path, notice: "Signed in successfully")
|
17
|
+
end
|
18
|
+
|
19
|
+
def create
|
20
|
+
if @user = User.find_by(email: params[:email], verified: true)
|
21
|
+
send_passwordless_email
|
22
|
+
redirect_to sign_in_path, notice: "Check your email for sign in instructions"
|
23
|
+
else
|
24
|
+
redirect_to new_sessions_passwordless_path, alert: "You can't sign in until you verify your email"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def set_user
|
30
|
+
@token = SignInToken.find_signed!(params[:sid]); @user = @token.user
|
31
|
+
rescue
|
32
|
+
redirect_to new_sessions_passwordless_path, alert: "That sign in link is invalid"
|
33
|
+
end
|
34
|
+
|
35
|
+
def send_passwordless_email
|
36
|
+
UserMailer.with(user: @user).passwordless.deliver_later
|
37
|
+
end
|
38
|
+
|
39
|
+
def revoke_tokens
|
40
|
+
@user.sign_in_tokens.delete_all
|
41
|
+
end
|
42
|
+
end
|
@@ -21,7 +21,6 @@ class SessionsController < ApplicationController
|
|
21
21
|
<%- if two_factor? -%>
|
22
22
|
if user.otp_secret
|
23
23
|
signed_id = user.signed_id(purpose: :authentication_challenge, expires_in: 20.minutes)
|
24
|
-
|
25
24
|
redirect_to new_two_factor_authentication_challenge_path(token: signed_id)
|
26
25
|
else
|
27
26
|
@session = user.sessions.create!
|
@@ -1,7 +1,4 @@
|
|
1
1
|
class TwoFactorAuthentication::TotpsController < ApplicationController
|
2
|
-
<%- if options.sudoable? -%>
|
3
|
-
before_action :require_sudo
|
4
|
-
<%- end -%>
|
5
2
|
before_action :set_user
|
6
3
|
before_action :set_totp
|
7
4
|
|
@@ -10,7 +7,9 @@ class TwoFactorAuthentication::TotpsController < ApplicationController
|
|
10
7
|
end
|
11
8
|
|
12
9
|
def create
|
13
|
-
if
|
10
|
+
if !@user.authenticate(params[:current_password])
|
11
|
+
redirect_to two_factor_authentication_totp_path, alert: "The password you entered is incorrect"
|
12
|
+
elsif @totp.verify(params[:code], drift_behind: 15)
|
14
13
|
@user.update! otp_secret: params[:secret]
|
15
14
|
redirect_to root_path, notice: "2FA is enabled on your account"
|
16
15
|
else
|
@@ -23,7 +23,12 @@
|
|
23
23
|
|
24
24
|
<div>
|
25
25
|
<%%= form.label :email, "New email", style: "display: block" %>
|
26
|
-
<%%= form.email_field :email %>
|
26
|
+
<%%= form.email_field :email, required: true, autofocus: true %>
|
27
|
+
</div>
|
28
|
+
|
29
|
+
<div>
|
30
|
+
<%%= form.label :current_password, style: "display: block" %>
|
31
|
+
<%%= form.password_field :current_password, required: true, autocomplete: "current-password" %>
|
27
32
|
</div>
|
28
33
|
|
29
34
|
<div>
|
@@ -5,7 +5,7 @@
|
|
5
5
|
<%%= form_with(url: identity_password_reset_path) do |form| %>
|
6
6
|
<div>
|
7
7
|
<%%= form.label :email, style: "display: block" %>
|
8
|
-
<%%= form.email_field :email,
|
8
|
+
<%%= form.email_field :email, required: true, autofocus: true %>
|
9
9
|
</div>
|
10
10
|
|
11
11
|
<div>
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<%%= form_with(url: sign_in_path) do |form| %>
|
7
7
|
<div>
|
8
8
|
<%%= form.label :email, style: "display: block" %>
|
9
|
-
<%%= form.email_field :email, value: params[:email_hint],
|
9
|
+
<%%= form.email_field :email, value: params[:email_hint], required: true, autofocus: true, autocomplete: "email" %>
|
10
10
|
</div>
|
11
11
|
|
12
12
|
<div>
|
@@ -18,6 +18,14 @@
|
|
18
18
|
<%%= form.submit "Sign in" %>
|
19
19
|
</div>
|
20
20
|
<%% end %>
|
21
|
+
|
22
|
+
<br>
|
23
|
+
|
24
|
+
<%- if passwordless? %>
|
25
|
+
<div>
|
26
|
+
<%%= link_to "Sign in without password", new_sessions_passwordless_path %>
|
27
|
+
</div>
|
28
|
+
<%- end -%>
|
21
29
|
<%- if omniauthable? %>
|
22
30
|
<div>
|
23
31
|
<%%= button_to "Sign in with OmniAuth", "/auth/developer", "data-turbo" => false %>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<p style="color: red"><%%= alert %></p>
|
2
|
+
|
3
|
+
<h1>Sign in without password</h1>
|
4
|
+
|
5
|
+
<%%= form_with(url: sessions_passwordless_path) do |form| %>
|
6
|
+
<div>
|
7
|
+
<%%= form.label :email, style: "display: block" %>
|
8
|
+
<%%= form.email_field :email, required: true, autofocus: true%>
|
9
|
+
</div>
|
10
|
+
|
11
|
+
<div>
|
12
|
+
<%%= form.submit "Sign in" %>
|
13
|
+
</div>
|
14
|
+
<%% end %>
|
data/lib/generators/authentication/templates/erb/two_factor_authentication/totps/new.html.erb.tt
CHANGED
@@ -19,7 +19,12 @@
|
|
19
19
|
|
20
20
|
<div>
|
21
21
|
<%%= form.label :code, "After scanning with your camera, the app will generate a six-digit code. Enter it here:", style: "display: block" %>
|
22
|
-
<%%= form.text_field :code,
|
22
|
+
<%%= form.text_field :code, required: true, autofocus: true, autocomplete: :off %>
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<div>
|
26
|
+
<%%= form.label :current_password, style: "display: block" %>
|
27
|
+
<%%= form.password_field :current_password, required: true, autocomplete: "current-password" %>
|
23
28
|
</div>
|
24
29
|
|
25
30
|
<div>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<p>Hey there,</p>
|
2
|
+
|
3
|
+
<p>You requested a magic sign-in link. Here you go:</p>
|
4
|
+
|
5
|
+
<%%= link_to "Sign in without password", edit_sessions_passwordless_url(sid: @signed_id) %>
|
6
|
+
|
7
|
+
<hr>
|
8
|
+
|
9
|
+
<p>Have questions or need help? Just reply to this email and our support team will help you sort it out.</p>
|
@@ -16,4 +16,12 @@ class UserMailer < ApplicationMailer
|
|
16
16
|
|
17
17
|
mail to: @user.email, subject: "Verify your email"
|
18
18
|
end
|
19
|
+
<%- if passwordless? %>
|
20
|
+
def passwordless
|
21
|
+
@user = params[:user]
|
22
|
+
@signed_id = @user.sign_in_tokens.create.signed_id(expires_in: 1.day)
|
23
|
+
|
24
|
+
mail to: @user.email, subject: "Your sign in link"
|
25
|
+
end
|
26
|
+
<%- end -%>
|
19
27
|
end
|
@@ -1,18 +1,10 @@
|
|
1
1
|
class Session < ApplicationRecord
|
2
2
|
belongs_to :user
|
3
|
-
<%- if options.sudoable? %>
|
4
|
-
kredis_flag :sudo, expires_in: 30.minutes
|
5
|
-
<%- end -%>
|
6
3
|
|
7
4
|
before_create do
|
8
5
|
self.user_agent = Current.user_agent
|
9
6
|
self.ip_address = Current.ip_address
|
10
7
|
end
|
11
|
-
<%- if options.sudoable? %>
|
12
|
-
after_create_commit do
|
13
|
-
self.sudo.mark
|
14
|
-
end
|
15
|
-
<%- end -%>
|
16
8
|
|
17
9
|
after_create_commit do
|
18
10
|
SessionMailer.with(session: self).signed_in_notification.deliver_later
|
@@ -3,6 +3,9 @@ class User < ApplicationRecord
|
|
3
3
|
|
4
4
|
has_many :email_verification_tokens, dependent: :destroy
|
5
5
|
has_many :password_reset_tokens, dependent: :destroy
|
6
|
+
<%- if passwordless? -%>
|
7
|
+
has_many :sign_in_tokens, dependent: :destroy
|
8
|
+
<%- end -%>
|
6
9
|
|
7
10
|
has_many :sessions, dependent: :destroy
|
8
11
|
<%- if options.trackable? -%>
|
@@ -22,7 +25,7 @@ class User < ApplicationRecord
|
|
22
25
|
self.email = email.downcase.strip
|
23
26
|
end
|
24
27
|
|
25
|
-
before_validation if: :email_changed?,
|
28
|
+
before_validation if: :email_changed?, on: :update do
|
26
29
|
self.verified = false
|
27
30
|
end
|
28
31
|
|
@@ -38,8 +41,8 @@ class User < ApplicationRecord
|
|
38
41
|
events.create! action: "password_changed"
|
39
42
|
end
|
40
43
|
|
41
|
-
after_update if: :verified_previously_changed? do
|
42
|
-
events.create! action: "email_verified"
|
44
|
+
after_update if: [:verified_previously_changed?, :verified?] do
|
45
|
+
events.create! action: "email_verified"
|
43
46
|
end
|
44
47
|
<%- end -%>
|
45
48
|
end
|
@@ -10,7 +10,14 @@ class Identity::EmailsControllerTest < ActionDispatch::IntegrationTest
|
|
10
10
|
end
|
11
11
|
|
12
12
|
test "should update email" do
|
13
|
-
patch identity_email_url, params: { email: "new_email@hey.com" }, headers: default_headers
|
13
|
+
patch identity_email_url, params: { email: "new_email@hey.com", current_password: "Secret1*3*5*" }, headers: default_headers
|
14
14
|
assert_response :success
|
15
15
|
end
|
16
|
+
|
17
|
+
test "should not update email with wrong current password" do
|
18
|
+
patch identity_email_url, params: { email: "new_email@hey.com", current_password: "SecretWrong1*3" }, headers: default_headers
|
19
|
+
|
20
|
+
assert_response :bad_request
|
21
|
+
assert_equal "The password you entered is incorrect", response.parsed_body["error"]
|
22
|
+
end
|
16
23
|
end
|
@@ -11,7 +11,14 @@ class Identity::EmailsControllerTest < ActionDispatch::IntegrationTest
|
|
11
11
|
end
|
12
12
|
|
13
13
|
test "should update email" do
|
14
|
-
patch identity_email_url, params: { email: "new_email@hey.com" }
|
14
|
+
patch identity_email_url, params: { email: "new_email@hey.com", current_password: "Secret1*3*5*" }
|
15
15
|
assert_redirected_to root_url
|
16
16
|
end
|
17
|
+
|
18
|
+
test "should not update email with wrong current password" do
|
19
|
+
patch identity_email_url, params: { email: "new_email@hey.com", current_password: "SecretWrong1*3" }
|
20
|
+
|
21
|
+
assert_redirected_to edit_identity_email_url
|
22
|
+
assert_equal "The password you entered is incorrect", flash[:alert]
|
23
|
+
end
|
17
24
|
end
|
@@ -9,6 +9,7 @@ class Identity::EmailsTest < ApplicationSystemTestCase
|
|
9
9
|
click_on "Change email address"
|
10
10
|
|
11
11
|
fill_in "New email", with: "new_email@hey.com"
|
12
|
+
fill_in "Current password", with: "Secret1*3*5*"
|
12
13
|
click_on "Save changes"
|
13
14
|
|
14
15
|
assert_text "Your email has been changed"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: authentication-zero
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.16.
|
4
|
+
version: 2.16.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nixon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-02-
|
11
|
+
date: 2023-02-14 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -44,7 +44,6 @@ files:
|
|
44
44
|
- lib/generators/authentication/templates/controllers/api/identity/password_resets_controller.rb.tt
|
45
45
|
- lib/generators/authentication/templates/controllers/api/passwords_controller.rb.tt
|
46
46
|
- lib/generators/authentication/templates/controllers/api/registrations_controller.rb.tt
|
47
|
-
- lib/generators/authentication/templates/controllers/api/sessions/sudos_controller.rb.tt
|
48
47
|
- lib/generators/authentication/templates/controllers/api/sessions_controller.rb.tt
|
49
48
|
- lib/generators/authentication/templates/controllers/html/application_controller.rb.tt
|
50
49
|
- lib/generators/authentication/templates/controllers/html/authentications/events_controller.rb.tt
|
@@ -55,7 +54,7 @@ files:
|
|
55
54
|
- lib/generators/authentication/templates/controllers/html/passwords_controller.rb.tt
|
56
55
|
- lib/generators/authentication/templates/controllers/html/registrations_controller.rb.tt
|
57
56
|
- lib/generators/authentication/templates/controllers/html/sessions/omniauth_controller.rb.tt
|
58
|
-
- lib/generators/authentication/templates/controllers/html/sessions/
|
57
|
+
- lib/generators/authentication/templates/controllers/html/sessions/passwordlesses_controller.rb.tt
|
59
58
|
- lib/generators/authentication/templates/controllers/html/sessions_controller.rb.tt
|
60
59
|
- lib/generators/authentication/templates/controllers/html/two_factor_authentication/challenges_controller.rb.tt
|
61
60
|
- lib/generators/authentication/templates/controllers/html/two_factor_authentication/totps_controller.rb.tt
|
@@ -69,23 +68,26 @@ files:
|
|
69
68
|
- lib/generators/authentication/templates/erb/session_mailer/signed_in_notification.html.erb.tt
|
70
69
|
- lib/generators/authentication/templates/erb/sessions/index.html.erb.tt
|
71
70
|
- lib/generators/authentication/templates/erb/sessions/new.html.erb.tt
|
72
|
-
- lib/generators/authentication/templates/erb/sessions/
|
71
|
+
- lib/generators/authentication/templates/erb/sessions/passwordlesses/new.html.erb.tt
|
73
72
|
- lib/generators/authentication/templates/erb/two_factor_authentication/challenges/new.html.erb.tt
|
74
73
|
- lib/generators/authentication/templates/erb/two_factor_authentication/totps/new.html.erb.tt
|
75
74
|
- lib/generators/authentication/templates/erb/user_mailer/email_verification.html.erb.tt
|
76
75
|
- lib/generators/authentication/templates/erb/user_mailer/password_reset.html.erb.tt
|
76
|
+
- lib/generators/authentication/templates/erb/user_mailer/passwordless.html.erb.tt
|
77
77
|
- lib/generators/authentication/templates/mailers/session_mailer.rb.tt
|
78
78
|
- lib/generators/authentication/templates/mailers/user_mailer.rb.tt
|
79
79
|
- lib/generators/authentication/templates/migrations/create_email_verification_tokens_migration.rb.tt
|
80
80
|
- lib/generators/authentication/templates/migrations/create_events_migration.rb.tt
|
81
81
|
- lib/generators/authentication/templates/migrations/create_password_reset_tokens_migration.rb.tt
|
82
82
|
- lib/generators/authentication/templates/migrations/create_sessions_migration.rb.tt
|
83
|
+
- lib/generators/authentication/templates/migrations/create_sign_in_tokens_migration.rb.tt
|
83
84
|
- lib/generators/authentication/templates/migrations/create_users_migration.rb.tt
|
84
85
|
- lib/generators/authentication/templates/models/current.rb.tt
|
85
86
|
- lib/generators/authentication/templates/models/email_verification_token.rb.tt
|
86
87
|
- lib/generators/authentication/templates/models/event.rb.tt
|
87
88
|
- lib/generators/authentication/templates/models/password_reset_token.rb.tt
|
88
89
|
- lib/generators/authentication/templates/models/session.rb.tt
|
90
|
+
- lib/generators/authentication/templates/models/sign_in_token.rb.tt
|
89
91
|
- lib/generators/authentication/templates/models/user.rb.tt
|
90
92
|
- lib/generators/authentication/templates/test_unit/application_system_test_case.rb.tt
|
91
93
|
- lib/generators/authentication/templates/test_unit/controllers/api/identity/email_verifications_controller_test.rb.tt
|
data/lib/generators/authentication/templates/controllers/api/sessions/sudos_controller.rb.tt
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
class Sessions::SudosController < ApplicationController
|
2
|
-
def create
|
3
|
-
session = Current.session
|
4
|
-
|
5
|
-
if session.user.authenticate(params[:password])
|
6
|
-
session.sudo.mark
|
7
|
-
else
|
8
|
-
render json: { error: "The password you entered is incorrect" }, status: :bad_request
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
data/lib/generators/authentication/templates/controllers/html/sessions/sudos_controller.rb.tt
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
class Sessions::SudosController < ApplicationController
|
2
|
-
def new
|
3
|
-
end
|
4
|
-
|
5
|
-
def create
|
6
|
-
session = Current.session
|
7
|
-
|
8
|
-
if session.user.authenticate(params[:password])
|
9
|
-
session.sudo.mark; redirect_to(params[:proceed_to_url])
|
10
|
-
else
|
11
|
-
redirect_to new_sessions_sudo_path(proceed_to_url: params[:proceed_to_url]), alert: "The password you entered is incorrect"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
<p style="color: red"><%%= alert %></p>
|
2
|
-
|
3
|
-
<h1>Enter your password to continue</h1>
|
4
|
-
|
5
|
-
<%%= form_with(url: sessions_sudo_path) do |form| %>
|
6
|
-
|
7
|
-
<%%= form.hidden_field :proceed_to_url, value: params[:proceed_to_url] %>
|
8
|
-
|
9
|
-
<div>
|
10
|
-
<%%= form.password_field :password, required: true, autofocus: true, autocomplete: "current-password" %>
|
11
|
-
</div>
|
12
|
-
|
13
|
-
<div>
|
14
|
-
<%%= form.submit "Continue" %>
|
15
|
-
</div>
|
16
|
-
<%% end %>
|
17
|
-
|
18
|
-
<br>
|
19
|
-
|
20
|
-
<p>
|
21
|
-
<strong>Why are you asking me to do this?</strong><br>
|
22
|
-
To better protect your account, we'll occasionally ask you to confirm your password before performing sensitive actions.
|
23
|
-
</p>
|
24
|
-
|
25
|
-
<p>
|
26
|
-
<strong>Forgot your password?</strong><br>
|
27
|
-
We'll help you <%%= link_to "reset it", new_identity_password_reset_path %> so you can continue.
|
28
|
-
</p>
|