authentication-zero 2.9.3 → 2.11.1
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/.rubocop.yml +15 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +1 -1
- data/README.md +8 -3
- data/authentication-zero-api.md +0 -3
- data/lib/authentication_zero/version.rb +1 -1
- data/lib/generators/authentication/authentication_generator.rb +34 -7
- data/lib/generators/authentication/templates/controllers/api/application_controller.rb.tt +3 -2
- data/lib/generators/authentication/templates/controllers/api/identity/emails_controller.rb.tt +3 -2
- data/lib/generators/authentication/templates/controllers/api/identity/password_resets_controller.rb.tt +4 -4
- data/lib/generators/authentication/templates/controllers/api/sessions/sudos_controller.rb.tt +1 -1
- data/lib/generators/authentication/templates/controllers/html/application_controller.rb.tt +3 -2
- data/lib/generators/authentication/templates/controllers/html/identity/emails_controller.rb.tt +3 -2
- data/lib/generators/authentication/templates/controllers/html/identity/password_resets_controller.rb.tt +4 -4
- data/lib/generators/authentication/templates/controllers/html/sessions/sudos_controller.rb.tt +4 -4
- data/lib/generators/authentication/templates/controllers/html/sessions_controller.rb.tt +13 -0
- data/lib/generators/authentication/templates/controllers/html/two_factor_authentication/challenges_controller.rb.tt +28 -0
- data/lib/generators/authentication/templates/controllers/html/two_factor_authentication/totps_controller.rb.tt +27 -0
- data/lib/generators/authentication/templates/erb/identity/emails/edit.html.erb.tt +5 -0
- data/lib/generators/authentication/templates/erb/identity/password_resets/edit.html.erb.tt +1 -1
- data/lib/generators/authentication/templates/erb/passwords/edit.html.erb.tt +2 -2
- data/lib/generators/authentication/templates/erb/sessions/sudos/new.html.erb.tt +2 -2
- data/lib/generators/authentication/templates/erb/two_factor_authentication/challenges/new.html.erb.tt +16 -0
- data/lib/generators/authentication/templates/erb/two_factor_authentication/totps/new.html.erb.tt +33 -0
- data/lib/generators/authentication/templates/migrations/create_sessions_migration.rb.tt +0 -3
- data/lib/generators/authentication/templates/migrations/create_table_migration.rb.tt +7 -4
- data/lib/generators/authentication/templates/models/model.rb.tt +6 -6
- data/lib/generators/authentication/templates/models/session.rb.tt +10 -3
- data/lib/generators/authentication/templates/test_unit/application_system_test_case.rb.tt +1 -1
- data/lib/generators/authentication/templates/test_unit/controllers/api/identity/email_verifications_controller_test.rb.tt +8 -4
- data/lib/generators/authentication/templates/test_unit/controllers/api/identity/emails_controller_test.rb.tt +9 -7
- data/lib/generators/authentication/templates/test_unit/controllers/api/identity/password_resets_controller_test.rb.tt +0 -3
- data/lib/generators/authentication/templates/test_unit/controllers/api/passwords_controller_test.rb.tt +6 -2
- data/lib/generators/authentication/templates/test_unit/controllers/api/sessions_controller_test.rb.tt +7 -3
- data/lib/generators/authentication/templates/test_unit/controllers/html/identity/emails_controller_test.rb.tt +5 -12
- data/lib/generators/authentication/templates/test_unit/controllers/html/identity/password_resets_controller_test.rb.tt +0 -3
- data/lib/generators/authentication/templates/test_unit/system/identity/emails_test.rb.tt +1 -0
- data/lib/generators/authentication/templates/test_unit/system/identity/password_resets_test.rb.tt +0 -3
- data/lib/generators/authentication/templates/test_unit/test_helper.rb.tt +3 -3
- metadata +7 -5
- data/lib/generators/authentication/templates/test_unit/controllers/api/sessions/sudos_controller_test.rb.tt +0 -20
- data/lib/generators/authentication/templates/test_unit/controllers/html/sessions/sudos_controller_test.rb.tt +0 -22
- data/lib/generators/authentication/templates/test_unit/system/sessions/sudos_test.rb.tt +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 26344aaefae4e99ea2048950089e5927a62d473f85d94596456006d6edbbc8ee
|
4
|
+
data.tar.gz: eebff7007c4754244993ac76b022081ccbd0201dac5cd1611ec84f8845e7a5d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ccd04a438745b60d071c9203c5e36588b01333a17e37a5ee1067c7007824d52fb2a3be0c5e4864868c393f9dec04e2284487651f7d7b0f908c238dcbf4a9dd2
|
7
|
+
data.tar.gz: 51b53ff133cdf9a69e42f29cadd19127646d6c98a6d476c1565c5e6151708b57f4076e1f19af4f4335b8bd6a08ac90b9328b6fe393f85d702dd7d415621a9c8a
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
inherit_from: https://raw.githubusercontent.com/rails/rails/master/.rubocop.yml
|
2
|
+
|
3
|
+
Performance:
|
4
|
+
Exclude:
|
5
|
+
- 'test/**/*'
|
6
|
+
|
7
|
+
Style/FrozenStringLiteralComment:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
Style/StringLiterals:
|
11
|
+
Enabled: true
|
12
|
+
EnforcedStyle: double_quotes
|
13
|
+
Include:
|
14
|
+
- 'app/**/*'
|
15
|
+
- 'test/**/*'
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## Authentication Zero 2.11.0 (March 27, 2022) ##
|
2
|
+
|
3
|
+
* Remove sudo from default generator
|
4
|
+
* Remove sudo_at from database
|
5
|
+
* Implement sudoable using redis
|
6
|
+
|
7
|
+
## Authentication Zero 2.10.0 (March 2, 2022) ##
|
8
|
+
|
9
|
+
* Implement two-factor
|
10
|
+
|
1
11
|
## Authentication Zero 2.9.0 (March 2, 2022) ##
|
2
12
|
|
3
13
|
* Implement trackable
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -11,8 +11,9 @@ The purpose of authentication zero is to generate a pre-built authentication sys
|
|
11
11
|
- Checks if a password has been found in any data breach (--pwned)
|
12
12
|
- Authentication by cookie
|
13
13
|
- Authentication by token (--api)
|
14
|
+
- Two factor authentication (--two-factor)
|
14
15
|
- Social Login with OmniAuth (--omniauthable)
|
15
|
-
- Ask password before sensitive data changes, aka: sudo
|
16
|
+
- Ask password before sensitive data changes, aka: sudo (--sudoable)
|
16
17
|
- Reset the user password and send reset instructions
|
17
18
|
- Reset the user password only from verified emails
|
18
19
|
- Lock sending reset password email after many attempts (--lockable)
|
@@ -53,7 +54,7 @@ root "home#index"
|
|
53
54
|
```
|
54
55
|
|
55
56
|
```
|
56
|
-
|
57
|
+
rails generate controller home index
|
57
58
|
```
|
58
59
|
|
59
60
|
Add these lines to your `app/views/home/index.html.erb`:
|
@@ -79,6 +80,10 @@ Add these lines to your `app/views/home/index.html.erb`:
|
|
79
80
|
<%# link_to "Activity Log", authentications_events_path %>
|
80
81
|
</div>
|
81
82
|
|
83
|
+
<div>
|
84
|
+
<%# link_to "Two-Factor Authentication", new_two_factor_authentication_totp_path %>
|
85
|
+
</div>
|
86
|
+
|
82
87
|
<br>
|
83
88
|
|
84
89
|
<%= button_to "Log out", Current.session, method: :delete %>
|
@@ -93,7 +98,7 @@ config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
|
|
93
98
|
## Usage
|
94
99
|
|
95
100
|
```
|
96
|
-
|
101
|
+
rails generate authentication user
|
97
102
|
```
|
98
103
|
|
99
104
|
Then run `bundle install` again!
|
data/authentication-zero-api.md
CHANGED
@@ -78,7 +78,6 @@ This endpoint will return `201 Created` with the current JSON representation of
|
|
78
78
|
"user_id": 1,
|
79
79
|
"user_agent": "insomnia/2022.1.0",
|
80
80
|
"ip_address": "127.0.0.1",
|
81
|
-
"sudo_at": "2022-03-04T17:20:33.632Z",
|
82
81
|
"created_at": "2022-03-04T17:20:33.632Z",
|
83
82
|
"updated_at": "2022-03-04T17:20:33.632Z"
|
84
83
|
},
|
@@ -87,7 +86,6 @@ This endpoint will return `201 Created` with the current JSON representation of
|
|
87
86
|
"user_id": 1,
|
88
87
|
"user_agent": "insomnia/2022.1.0",
|
89
88
|
"ip_address": "127.0.0.1",
|
90
|
-
"sudo_at": "2022-03-04T17:14:03.386Z",
|
91
89
|
"created_at": "2022-03-04T17:14:03.386Z",
|
92
90
|
"updated_at": "2022-03-04T17:14:03.386Z"
|
93
91
|
}
|
@@ -106,7 +104,6 @@ This endpoint will return `201 Created` with the current JSON representation of
|
|
106
104
|
"user_id": 1,
|
107
105
|
"user_agent": "insomnia/2022.1.0",
|
108
106
|
"ip_address": "127.0.0.1",
|
109
|
-
"sudo_at": "2022-03-04T17:14:03.386Z",
|
110
107
|
"created_at": "2022-03-04T17:14:03.386Z",
|
111
108
|
"updated_at": "2022-03-04T17:14:03.386Z"
|
112
109
|
}
|
@@ -5,17 +5,19 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
|
|
5
5
|
|
6
6
|
class_option :api, type: :boolean, desc: "Generates API authentication"
|
7
7
|
class_option :pwned, type: :boolean, desc: "Add pwned password validation"
|
8
|
+
class_option :sudoable, type: :boolean, desc: "Add password request before sensitive data changes"
|
8
9
|
class_option :lockable, type: :boolean, desc: "Add password reset locking"
|
9
10
|
class_option :ratelimit, type: :boolean, desc: "Add request rate limiting"
|
10
11
|
class_option :omniauthable, type: :boolean, desc: "Add social login support"
|
11
12
|
class_option :trackable, type: :boolean, desc: "Add activity log support"
|
13
|
+
class_option :two_factor, type: :boolean, desc: "Add two factor authentication"
|
12
14
|
|
13
15
|
source_root File.expand_path("templates", __dir__)
|
14
16
|
|
15
17
|
def add_gems
|
16
18
|
uncomment_lines "Gemfile", /"bcrypt"/
|
17
|
-
uncomment_lines "Gemfile", /"redis"/ if
|
18
|
-
uncomment_lines "Gemfile", /"kredis"/ if
|
19
|
+
uncomment_lines "Gemfile", /"redis"/ if redis?
|
20
|
+
uncomment_lines "Gemfile", /"kredis"/ if redis?
|
19
21
|
|
20
22
|
if options.pwned?
|
21
23
|
gem "pwned", comment: "Use Pwned to check if a password has been found in any of the huge data breaches [https://github.com/philnash/pwned]"
|
@@ -29,10 +31,15 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
|
|
29
31
|
gem "omniauth", comment: "Use OmniAuth to support multi-provider authentication [https://github.com/omniauth/omniauth]"
|
30
32
|
gem "omniauth-rails_csrf_protection", comment: "Provides a mitigation against CVE-2015-9284 [https://github.com/cookpad/omniauth-rails_csrf_protection]"
|
31
33
|
end
|
34
|
+
|
35
|
+
if two_factor?
|
36
|
+
gem "rotp", comment: "Use rotp for generating and validating one time passwords [https://github.com/mdp/rotp]"
|
37
|
+
gem "rqrcode", comment: "Use rqrcode for creating and rendering QR codes into various formats [https://github.com/whomwah/rqrcode]"
|
38
|
+
end
|
32
39
|
end
|
33
40
|
|
34
41
|
def create_configuration_files
|
35
|
-
copy_file "config/redis/shared.yml", "config/redis/shared.yml" if
|
42
|
+
copy_file "config/redis/shared.yml", "config/redis/shared.yml" if redis?
|
36
43
|
copy_file "config/initializers/omniauth.rb", "config/initializers/omniauth.rb" if omniauthable?
|
37
44
|
end
|
38
45
|
|
@@ -67,10 +74,11 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
|
|
67
74
|
template "controllers/#{format_folder}/application_controller.rb", "app/controllers/application_controller.rb", force: true
|
68
75
|
|
69
76
|
directory "controllers/#{format_folder}/identity", "app/controllers/identity"
|
77
|
+
directory "controllers/#{format_folder}/two_factor_authentication", "app/controllers/two_factor_authentication" if two_factor?
|
78
|
+
template "controllers/#{format_folder}/sessions_controller.rb", "app/controllers/sessions_controller.rb"
|
70
79
|
template "controllers/#{format_folder}/passwords_controller.rb", "app/controllers/passwords_controller.rb"
|
71
80
|
template "controllers/#{format_folder}/registrations_controller.rb", "app/controllers/registrations_controller.rb"
|
72
|
-
template "controllers/#{format_folder}/
|
73
|
-
template "controllers/#{format_folder}/sessions/sudos_controller.rb", "app/controllers/sessions/sudos_controller.rb"
|
81
|
+
template "controllers/#{format_folder}/sessions/sudos_controller.rb", "app/controllers/sessions/sudos_controller.rb" if options.sudoable?
|
74
82
|
template "controllers/#{format_folder}/sessions/omniauth_controller.rb", "app/controllers/sessions/omniauth_controller.rb" if omniauthable?
|
75
83
|
template "controllers/#{format_folder}/authentications/events_controller.rb", "app/controllers/authentications/events_controller.rb" if options.trackable?
|
76
84
|
end
|
@@ -86,7 +94,13 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
|
|
86
94
|
directory "erb/identity", "app/views/identity"
|
87
95
|
directory "erb/passwords", "app/views/passwords"
|
88
96
|
directory "erb/registrations", "app/views/registrations"
|
89
|
-
|
97
|
+
|
98
|
+
template "erb/sessions/index.html.erb", "app/views/sessions/index.html.erb"
|
99
|
+
template "erb/sessions/new.html.erb", "app/views/sessions/new.html.erb"
|
100
|
+
|
101
|
+
directory "erb/sessions/sudos", "app/views/sessions/sudos" if options.sudoable?
|
102
|
+
|
103
|
+
directory "erb/two_factor_authentication", "app/views/two_factor_authentication" if two_factor?
|
90
104
|
directory "erb/authentications/events", "app/views/authentications/events" if options.trackable?
|
91
105
|
end
|
92
106
|
end
|
@@ -102,6 +116,11 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
|
|
102
116
|
route "get '/auth/failure', to: 'sessions/omniauth#failure'"
|
103
117
|
end
|
104
118
|
|
119
|
+
if two_factor?
|
120
|
+
route "resource :totp, only: [:new, :create]", namespace: :two_factor_authentication
|
121
|
+
route "resource :challenge, only: [:new, :create]", namespace: :two_factor_authentication
|
122
|
+
end
|
123
|
+
|
105
124
|
if options.trackable?
|
106
125
|
route "resources :events, only: :index", namespace: :authentications
|
107
126
|
end
|
@@ -109,7 +128,7 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
|
|
109
128
|
route "resource :password_reset, only: [:new, :edit, :create, :update]", namespace: :identity
|
110
129
|
route "resource :email_verification, only: [:edit, :create]", namespace: :identity
|
111
130
|
route "resource :email, only: [:edit, :update]", namespace: :identity
|
112
|
-
route "resource :sudo, only: [:new, :create]", namespace: :sessions
|
131
|
+
route "resource :sudo, only: [:new, :create]", namespace: :sessions if options.sudoable?
|
113
132
|
route "resource :password, only: [:edit, :update]"
|
114
133
|
route "resources :sessions, only: [:index, :show, :destroy]"
|
115
134
|
route "post 'sign_up', to: 'registrations#create'"
|
@@ -133,4 +152,12 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
|
|
133
152
|
def omniauthable?
|
134
153
|
options.omniauthable? && !options.api?
|
135
154
|
end
|
155
|
+
|
156
|
+
def two_factor?
|
157
|
+
options.two_factor? && !options.api?
|
158
|
+
end
|
159
|
+
|
160
|
+
def redis?
|
161
|
+
options.lockable? || options.sudoable?
|
162
|
+
end
|
136
163
|
end
|
@@ -3,12 +3,13 @@ class ApplicationController < ActionController::API
|
|
3
3
|
|
4
4
|
before_action :set_current_request_details
|
5
5
|
before_action :authenticate
|
6
|
-
|
6
|
+
<%- if options.sudoable? %>
|
7
7
|
def require_sudo
|
8
|
-
|
8
|
+
unless Current.session.sudo?
|
9
9
|
render json: { error: "Enter your password to continue" }, status: :forbidden
|
10
10
|
end
|
11
11
|
end
|
12
|
+
<%- end -%>
|
12
13
|
|
13
14
|
private
|
14
15
|
def authenticate
|
data/lib/generators/authentication/templates/controllers/api/identity/emails_controller.rb.tt
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
class Identity::EmailsController < ApplicationController
|
2
|
-
before_action :require_sudo
|
3
2
|
before_action :set_<%= singular_table_name %>
|
4
3
|
|
5
4
|
def update
|
6
|
-
if
|
5
|
+
if !@<%= singular_table_name %>.authenticate(params[:current_password])
|
6
|
+
render json: { error: "The password you entered is incorrect" }, status: :bad_request
|
7
|
+
elsif @<%= singular_table_name %>.update(<%= "#{singular_table_name}_params" %>)
|
7
8
|
render json: @<%= singular_table_name %>
|
8
9
|
else
|
9
10
|
render json: @<%= singular_table_name %>.errors, status: :unprocessable_entity
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class Identity::PasswordResetsController < ApplicationController
|
2
2
|
skip_before_action :authenticate
|
3
3
|
|
4
|
-
|
4
|
+
<%- if options.lockable? -%>
|
5
5
|
before_action :require_locking, only: :create
|
6
|
-
|
6
|
+
<%- end -%>
|
7
7
|
before_action :set_<%= singular_table_name %>, only: :update
|
8
8
|
|
9
9
|
def create
|
@@ -32,11 +32,11 @@ class Identity::PasswordResetsController < ApplicationController
|
|
32
32
|
def <%= "#{singular_table_name}_params" %>
|
33
33
|
params.permit(:password, :password_confirmation)
|
34
34
|
end
|
35
|
-
|
35
|
+
<%- if options.lockable? %>
|
36
36
|
def require_locking
|
37
37
|
Locking.lock_on("password_reset_lock:#{request.remote_ip}", wait: 1.hour, attempts: 10) do
|
38
38
|
render json: { error: "You've exceeded the maximum number of attempts" }, status: :too_many_requests
|
39
39
|
end
|
40
40
|
end
|
41
|
-
|
41
|
+
<%- end -%>
|
42
42
|
end
|
data/lib/generators/authentication/templates/controllers/api/sessions/sudos_controller.rb.tt
CHANGED
@@ -3,7 +3,7 @@ class Sessions::SudosController < ApplicationController
|
|
3
3
|
session = Current.session
|
4
4
|
|
5
5
|
if session.<%= singular_table_name %>.authenticate(params[:password])
|
6
|
-
session.
|
6
|
+
session.sudo.mark
|
7
7
|
else
|
8
8
|
render json: { error: "The password you entered is incorrect" }, status: :bad_request
|
9
9
|
end
|
@@ -1,12 +1,13 @@
|
|
1
1
|
class ApplicationController < ActionController::Base
|
2
2
|
before_action :set_current_request_details
|
3
3
|
before_action :authenticate
|
4
|
-
|
4
|
+
<%- if options.sudoable? %>
|
5
5
|
def require_sudo
|
6
|
-
|
6
|
+
unless Current.session.sudo?
|
7
7
|
redirect_to new_sessions_sudo_path(proceed_to_url: request.url)
|
8
8
|
end
|
9
9
|
end
|
10
|
+
<%- end -%>
|
10
11
|
|
11
12
|
private
|
12
13
|
def authenticate
|
data/lib/generators/authentication/templates/controllers/html/identity/emails_controller.rb.tt
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
class Identity::EmailsController < ApplicationController
|
2
|
-
before_action :require_sudo
|
3
2
|
before_action :set_<%= singular_table_name %>
|
4
3
|
|
5
4
|
def edit
|
6
5
|
end
|
7
6
|
|
8
7
|
def update
|
9
|
-
if
|
8
|
+
if !@<%= singular_table_name %>.authenticate(params[:current_password])
|
9
|
+
redirect_to edit_identity_email_path, alert: "The password you entered is incorrect"
|
10
|
+
elsif @<%= singular_table_name %>.update(<%= "#{singular_table_name}_params" %>)
|
10
11
|
redirect_to root_path, notice: "Your email has been changed"
|
11
12
|
else
|
12
13
|
render :edit, status: :unprocessable_entity
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class Identity::PasswordResetsController < ApplicationController
|
2
2
|
skip_before_action :authenticate
|
3
3
|
|
4
|
-
|
4
|
+
<%- if options.lockable? -%>
|
5
5
|
before_action :require_locking, only: :create
|
6
|
-
|
6
|
+
<%- end -%>
|
7
7
|
before_action :set_<%= singular_table_name %>, only: %i[ edit update ]
|
8
8
|
|
9
9
|
def new
|
@@ -39,11 +39,11 @@ class Identity::PasswordResetsController < ApplicationController
|
|
39
39
|
def <%= "#{singular_table_name}_params" %>
|
40
40
|
params.permit(:password, :password_confirmation)
|
41
41
|
end
|
42
|
-
|
42
|
+
<%- if options.lockable? %>
|
43
43
|
def require_locking
|
44
44
|
Locking.lock_on("password_reset_lock:#{request.remote_ip}", wait: 1.hour, attempts: 10) do
|
45
45
|
redirect_to new_identity_password_reset_path, alert: "You've exceeded the maximum number of attempts"
|
46
46
|
end
|
47
47
|
end
|
48
|
-
|
48
|
+
<%- end -%>
|
49
49
|
end
|
data/lib/generators/authentication/templates/controllers/html/sessions/sudos_controller.rb.tt
CHANGED
@@ -5,12 +5,12 @@ class Sessions::SudosController < ApplicationController
|
|
5
5
|
def create
|
6
6
|
session = Current.session
|
7
7
|
|
8
|
-
|
8
|
+
<%- if omniauthable? -%>
|
9
9
|
if session.<%= singular_table_name %>.authenticate(params[:password]) || session.<%= singular_table_name %>.provider
|
10
|
-
|
10
|
+
<%- else -%>
|
11
11
|
if session.<%= singular_table_name %>.authenticate(params[:password])
|
12
|
-
|
13
|
-
session.
|
12
|
+
<%- end -%>
|
13
|
+
session.sudo.mark; redirect_to(params[:proceed_to_url])
|
14
14
|
else
|
15
15
|
redirect_to new_sessions_sudo_path(proceed_to_url: params[:proceed_to_url]), alert: "The password you entered is incorrect"
|
16
16
|
end
|
@@ -15,10 +15,23 @@ class SessionsController < ApplicationController
|
|
15
15
|
<%= singular_table_name %> = <%= class_name %>.find_by(email: params[:email])
|
16
16
|
|
17
17
|
if <%= singular_table_name %> && <%= singular_table_name %>.authenticate(params[:password])
|
18
|
+
<%- if two_factor? -%>
|
19
|
+
if <%= singular_table_name %>.otp_secret
|
20
|
+
signed_id = <%= singular_table_name %>.signed_id(purpose: :authentication_challenge, expires_in: 20.minutes)
|
21
|
+
|
22
|
+
redirect_to new_two_factor_authentication_challenge_path(token: signed_id)
|
23
|
+
else
|
24
|
+
@session = <%= singular_table_name %>.sessions.create!
|
25
|
+
cookies.signed.permanent[:session_token] = { value: @session.id, httponly: true }
|
26
|
+
|
27
|
+
redirect_to root_path, notice: "Signed in successfully"
|
28
|
+
end
|
29
|
+
<%- else -%>
|
18
30
|
@session = <%= singular_table_name %>.sessions.create!
|
19
31
|
cookies.signed.permanent[:session_token] = { value: @session.id, httponly: true }
|
20
32
|
|
21
33
|
redirect_to root_path, notice: "Signed in successfully"
|
34
|
+
<%- end -%>
|
22
35
|
else
|
23
36
|
redirect_to sign_in_path(email_hint: params[:email]), alert: "That email or password is incorrect"
|
24
37
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class TwoFactorAuthentication::ChallengesController < ApplicationController
|
2
|
+
skip_before_action :authenticate
|
3
|
+
|
4
|
+
before_action :set_<%= singular_table_name %>
|
5
|
+
|
6
|
+
def new
|
7
|
+
end
|
8
|
+
|
9
|
+
def create
|
10
|
+
@totp = ROTP::TOTP.new(@<%= singular_table_name %>.otp_secret, issuer: "YourAppName")
|
11
|
+
|
12
|
+
if @totp.verify(params[:code], drift_behind: 15)
|
13
|
+
session = @<%= singular_table_name %>.sessions.create!
|
14
|
+
cookies.signed.permanent[:session_token] = { value: session.id, httponly: true }
|
15
|
+
|
16
|
+
redirect_to root_path, notice: "Signed in successfully"
|
17
|
+
else
|
18
|
+
redirect_to new_two_factor_authentication_challenge_path(token: params[:token]), alert: "That code didn't work. Please try again"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def set_<%= singular_table_name %>
|
24
|
+
@<%= singular_table_name %> = <%= class_name %>.find_signed!(params[:token], purpose: :authentication_challenge)
|
25
|
+
rescue
|
26
|
+
redirect_to sign_in_path, alert: "That's taking too long. Please re-enter your password and try again"
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class TwoFactorAuthentication::TotpsController < ApplicationController
|
2
|
+
before_action :set_<%= singular_table_name %>
|
3
|
+
before_action :set_totp
|
4
|
+
|
5
|
+
def new
|
6
|
+
@qr_code = RQRCode::QRCode.new(@totp.provisioning_uri(@<%= singular_table_name %>.email))
|
7
|
+
end
|
8
|
+
|
9
|
+
def create
|
10
|
+
if !@<%= singular_table_name %>.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)
|
13
|
+
@<%= singular_table_name %>.update! otp_secret: params[:secret]
|
14
|
+
redirect_to root_path, notice: "2FA is enabled on your account"
|
15
|
+
else
|
16
|
+
redirect_to two_factor_authentication_totp_path, alert: "That code didn't work. Please try again"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def set_<%= singular_table_name %>
|
21
|
+
@<%= singular_table_name %> = Current.<%= singular_table_name %>
|
22
|
+
end
|
23
|
+
|
24
|
+
def set_totp
|
25
|
+
@totp = ROTP::TOTP.new(params[:secret] || ROTP::Base32.random, issuer: "YourAppName")
|
26
|
+
end
|
27
|
+
end
|
@@ -21,6 +21,11 @@
|
|
21
21
|
</div>
|
22
22
|
<%% end %>
|
23
23
|
|
24
|
+
<div>
|
25
|
+
<%%= form.label :current_password, style: "display: block" %>
|
26
|
+
<%%= form.password_field :current_password, required: true, autofocus: true, autocomplete: "current-password" %>
|
27
|
+
</div>
|
28
|
+
|
24
29
|
<div>
|
25
30
|
<%%= form.label :email, "New email", style: "display: block" %>
|
26
31
|
<%%= form.email_field :email %>
|
@@ -16,8 +16,8 @@
|
|
16
16
|
<%% end %>
|
17
17
|
|
18
18
|
<div>
|
19
|
-
<%%=
|
20
|
-
<%%=
|
19
|
+
<%%= form.label :current_password, style: "display: block" %>
|
20
|
+
<%%= form.password_field :current_password, required: true, autofocus: true, autocomplete: "current-password" %>
|
21
21
|
</div>
|
22
22
|
|
23
23
|
<div>
|
@@ -4,10 +4,10 @@
|
|
4
4
|
|
5
5
|
<%%= form_with(url: sessions_sudo_path) do |form| %>
|
6
6
|
|
7
|
-
<%%=
|
7
|
+
<%%= form.hidden_field :proceed_to_url, value: params[:proceed_to_url] %>
|
8
8
|
|
9
9
|
<div>
|
10
|
-
<%%=
|
10
|
+
<%%= form.password_field :password, required: true, autofocus: true, autocomplete: "current-password" %>
|
11
11
|
</div>
|
12
12
|
|
13
13
|
<div>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<p style="color: red"><%%= alert %></p>
|
2
|
+
|
3
|
+
<%%= form_with(url: two_factor_authentication_challenge_path) do |form| %>
|
4
|
+
<%%= form.hidden_field :token, value: params[:token] %>
|
5
|
+
|
6
|
+
<div>
|
7
|
+
<%%= form.label :code do %>
|
8
|
+
<h1>Next, open the 2FA authenticator app on your phone and type the six digit code below:</h1>
|
9
|
+
<%% end %>
|
10
|
+
<%%= form.text_field :code, autofocus: true, required: true, autocomplete: :off %>
|
11
|
+
</div>
|
12
|
+
|
13
|
+
<div>
|
14
|
+
<%%= form.submit "Verify" %>
|
15
|
+
</div>
|
16
|
+
<%% end %>
|
data/lib/generators/authentication/templates/erb/two_factor_authentication/totps/new.html.erb.tt
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
<p style="color: red"><%%= alert %></p>
|
2
|
+
|
3
|
+
<h1>Upgrade your security with 2FA</h1>
|
4
|
+
|
5
|
+
<h2>Step 1: Get an Authenticator App</h2>
|
6
|
+
<p>First, you'll need a 2FA authenticator app on your phone. <strong>If you already have one, skip to step 2.</strong></p>
|
7
|
+
<p><strong>If you don't have one, or you aren't sure, we recommend Microsoft Authenticator</strong>. You can download it free on the Apple App Store for iPhone, or Google Play Store for Android. Please grab your phone, search the store, and install it now.</p>
|
8
|
+
|
9
|
+
<h2>Step 2: Scan + Enter the Code</h2>
|
10
|
+
<p>Next, open the authenticator app, tap "Scan QR code" or "+", and, when it asks, point your phone's camera at this QR code picture below.</p>
|
11
|
+
|
12
|
+
<figure>
|
13
|
+
<%%= image_tag @qr_code.as_png(resize_exactly_to: 200).to_data_url%>
|
14
|
+
<figcaption>Point your camera here</figcaption>
|
15
|
+
</figure>
|
16
|
+
|
17
|
+
<%%= form_with(url: two_factor_authentication_totp_path) do |form| %>
|
18
|
+
<%%= form.hidden_field :secret, value: @totp.secret %>
|
19
|
+
|
20
|
+
<div>
|
21
|
+
<%%= form.label :current_password, style: "display: block" %>
|
22
|
+
<%%= form.password_field :current_password, required: true, autofocus: true, autocomplete: "current-password" %>
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<div>
|
26
|
+
<%%= form.label :code, "After scanning with your camera, the app will generate a six-digit code. Enter it here:", style: "display: block" %>
|
27
|
+
<%%= form.text_field :code, autofocus: true, required: true, autocomplete: :off %>
|
28
|
+
</div>
|
29
|
+
|
30
|
+
<div>
|
31
|
+
<%%= form.submit "Verify and active" %>
|
32
|
+
</div>
|
33
|
+
<%% end %>
|
@@ -2,12 +2,9 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
|
|
2
2
|
def change
|
3
3
|
create_table :sessions do |t|
|
4
4
|
t.references :<%= singular_table_name %>, null: false, foreign_key: true
|
5
|
-
|
6
5
|
t.string :user_agent
|
7
6
|
t.string :ip_address
|
8
7
|
|
9
|
-
t.datetime :sudo_at, null: false
|
10
|
-
|
11
8
|
t.timestamps
|
12
9
|
end
|
13
10
|
end
|
@@ -5,17 +5,20 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
|
|
5
5
|
t.string :password_digest, null: false
|
6
6
|
|
7
7
|
t.boolean :verified, null: false, default: false
|
8
|
-
|
8
|
+
<%- if two_factor? %>
|
9
|
+
t.string :otp_secret
|
10
|
+
<%- end -%>
|
11
|
+
<%- if omniauthable? %>
|
9
12
|
t.string :provider
|
10
13
|
t.string :uid
|
11
|
-
|
14
|
+
<%- end -%>
|
12
15
|
|
13
16
|
t.timestamps
|
14
17
|
end
|
15
18
|
|
16
19
|
add_index :<%= table_name %>, :email, unique: true
|
17
|
-
|
20
|
+
<%- if omniauthable? -%>
|
18
21
|
add_index :<%= table_name %>, [:provider, :uid], unique: true
|
19
|
-
|
22
|
+
<%- end -%>
|
20
23
|
end
|
21
24
|
end
|
@@ -2,18 +2,18 @@ class <%= class_name %> < ApplicationRecord
|
|
2
2
|
has_secure_password
|
3
3
|
|
4
4
|
has_many :sessions, dependent: :destroy
|
5
|
-
|
5
|
+
<%- if options.trackable? -%>
|
6
6
|
has_many :events, dependent: :destroy
|
7
|
-
|
7
|
+
<%- end -%>
|
8
8
|
|
9
9
|
validates :email, presence: true, uniqueness: true
|
10
10
|
validates_format_of :email, with: /\A[^@\s]+@[^@\s]+\z/
|
11
11
|
|
12
12
|
validates_length_of :password, minimum: 12, allow_nil: true
|
13
13
|
validates_format_of :password, with: /(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])/, allow_nil: true, message: "might easily be guessed"
|
14
|
-
|
14
|
+
<%- if options.pwned? -%>
|
15
15
|
validates :password, not_pwned: { message: "might easily be guessed" }
|
16
|
-
|
16
|
+
<%- end -%>
|
17
17
|
|
18
18
|
before_validation do
|
19
19
|
self.email = email.downcase.strip
|
@@ -30,7 +30,7 @@ class <%= class_name %> < ApplicationRecord
|
|
30
30
|
after_save_commit if: :email_previously_changed? do
|
31
31
|
IdentityMailer.with(user: self).email_verify_confirmation.deliver_later
|
32
32
|
end
|
33
|
-
|
33
|
+
<%- if options.trackable? %>
|
34
34
|
after_save_commit if: :email_previously_changed? do
|
35
35
|
events.create! action: "email_verification_requested"
|
36
36
|
end
|
@@ -42,5 +42,5 @@ class <%= class_name %> < ApplicationRecord
|
|
42
42
|
after_update if: :verified_previously_changed? do
|
43
43
|
events.create! action: "email_verified" if verified?
|
44
44
|
end
|
45
|
-
|
45
|
+
<%- end -%>
|
46
46
|
end
|
@@ -1,16 +1,23 @@
|
|
1
1
|
class Session < ApplicationRecord
|
2
2
|
belongs_to :<%= singular_table_name %>
|
3
|
+
<%- if options.sudoable? %>
|
4
|
+
kredis_flag :sudo, expires_in: 30.minutes
|
5
|
+
<%- end -%>
|
3
6
|
|
4
7
|
before_create do
|
5
8
|
self.user_agent = Current.user_agent
|
6
9
|
self.ip_address = Current.ip_address
|
7
|
-
self.sudo_at = Time.current
|
8
10
|
end
|
11
|
+
<%- if options.sudoable? %>
|
12
|
+
after_create_commit do
|
13
|
+
self.sudo.mark
|
14
|
+
end
|
15
|
+
<%- end -%>
|
9
16
|
|
10
17
|
after_create_commit do
|
11
18
|
SessionMailer.with(session: self).signed_in_notification.deliver_later
|
12
19
|
end
|
13
|
-
|
20
|
+
<%- if options.trackable? %>
|
14
21
|
after_create do
|
15
22
|
<%= singular_table_name %>.events.create! action: "signed_in"
|
16
23
|
end
|
@@ -18,5 +25,5 @@ class Session < ApplicationRecord
|
|
18
25
|
after_destroy do
|
19
26
|
<%= singular_table_name %>.events.create! action: "signed_out"
|
20
27
|
end
|
21
|
-
|
28
|
+
<%- end -%>
|
22
29
|
end
|
@@ -9,21 +9,25 @@ class Identity::EmailVerificationsControllerTest < ActionDispatch::IntegrationTe
|
|
9
9
|
@<%= singular_table_name %>.update! verified: false
|
10
10
|
end
|
11
11
|
|
12
|
+
def default_headers
|
13
|
+
{ "Authorization" => "Bearer #{@token}" }
|
14
|
+
end
|
15
|
+
|
12
16
|
test "should send a verification email" do
|
13
17
|
assert_enqueued_email_with IdentityMailer, :email_verify_confirmation, args: { <%= singular_table_name %>: @<%= singular_table_name %> } do
|
14
|
-
post identity_email_verification_url, headers:
|
18
|
+
post identity_email_verification_url, headers: default_headers
|
15
19
|
end
|
16
20
|
|
17
21
|
assert_response :no_content
|
18
22
|
end
|
19
23
|
|
20
24
|
test "should verify email" do
|
21
|
-
get edit_identity_email_verification_url, params: { token: @sid, email: @<%= singular_table_name %>.email }, headers:
|
25
|
+
get edit_identity_email_verification_url, params: { token: @sid, email: @<%= singular_table_name %>.email }, headers: default_headers
|
22
26
|
assert_response :no_content
|
23
27
|
end
|
24
28
|
|
25
29
|
test "should not verify email with expired token" do
|
26
|
-
get edit_identity_email_verification_url, params: { token: @sid_exp, email: @<%= singular_table_name %>.email }, headers:
|
30
|
+
get edit_identity_email_verification_url, params: { token: @sid_exp, email: @<%= singular_table_name %>.email }, headers: default_headers
|
27
31
|
|
28
32
|
assert_response :bad_request
|
29
33
|
assert_equal "That email verification link is invalid", response.parsed_body["error"]
|
@@ -32,7 +36,7 @@ class Identity::EmailVerificationsControllerTest < ActionDispatch::IntegrationTe
|
|
32
36
|
test "should not verify email with previous token" do
|
33
37
|
@<%= singular_table_name %>.update! email: "other_email@hey.com"
|
34
38
|
|
35
|
-
get edit_identity_email_verification_url, params: { token: @sid, email: @<%= singular_table_name %>.email_previously_was }, headers:
|
39
|
+
get edit_identity_email_verification_url, params: { token: @sid, email: @<%= singular_table_name %>.email_previously_was }, headers: default_headers
|
36
40
|
|
37
41
|
assert_response :bad_request
|
38
42
|
assert_equal "That email verification link is invalid", response.parsed_body["error"]
|
@@ -5,17 +5,19 @@ class Identity::EmailsControllerTest < ActionDispatch::IntegrationTest
|
|
5
5
|
@<%= singular_table_name %>, @token = sign_in_as(<%= table_name %>(:lazaro_nixon))
|
6
6
|
end
|
7
7
|
|
8
|
+
def default_headers
|
9
|
+
{ "Authorization" => "Bearer #{@token}" }
|
10
|
+
end
|
11
|
+
|
8
12
|
test "should update email" do
|
9
|
-
patch identity_email_url, params: { email: "new_email@hey.com"
|
13
|
+
patch identity_email_url, params: { email: "new_email@hey.com", current_password: "Secret1*3*5*" }, headers: default_headers
|
10
14
|
assert_response :success
|
11
15
|
end
|
12
16
|
|
13
|
-
test "should not update email
|
14
|
-
|
15
|
-
|
16
|
-
patch identity_email_url, params: { email: "new_email@hey.com" }, headers: { "Authorization" => "Bearer #{@token}" }
|
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
|
17
19
|
|
18
|
-
assert_response :
|
19
|
-
assert_equal "
|
20
|
+
assert_response :bad_request
|
21
|
+
assert_equal "The password you entered is incorrect", response.parsed_body["error"]
|
20
22
|
end
|
21
23
|
end
|
@@ -6,9 +6,6 @@ class Identity::PasswordResetsControllerTest < ActionDispatch::IntegrationTest
|
|
6
6
|
@sid = @<%= singular_table_name %>.signed_id(purpose: :password_reset, expires_in: 20.minutes)
|
7
7
|
@sid_exp = @<%= singular_table_name %>.signed_id(purpose: :password_reset, expires_in: 0.minutes)
|
8
8
|
end
|
9
|
-
<% if options.lockable? %>
|
10
|
-
teardown { Kredis.clear_all }
|
11
|
-
<% end -%>
|
12
9
|
|
13
10
|
test "should send a password reset email" do
|
14
11
|
assert_enqueued_email_with IdentityMailer, :password_reset_provision, args: { <%= singular_table_name %>: @<%= singular_table_name %> } do
|
@@ -5,13 +5,17 @@ class PasswordsControllerTest < ActionDispatch::IntegrationTest
|
|
5
5
|
@<%= singular_table_name %>, @token = sign_in_as(<%= table_name %>(:lazaro_nixon))
|
6
6
|
end
|
7
7
|
|
8
|
+
def default_headers
|
9
|
+
{ "Authorization" => "Bearer #{@token}" }
|
10
|
+
end
|
11
|
+
|
8
12
|
test "should update password" do
|
9
|
-
patch password_url, params: { current_password: "Secret1*3*5*", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }, headers:
|
13
|
+
patch password_url, params: { current_password: "Secret1*3*5*", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }, headers: default_headers
|
10
14
|
assert_response :success
|
11
15
|
end
|
12
16
|
|
13
17
|
test "should not update password with wrong current password" do
|
14
|
-
patch password_url, params: { current_password: "SecretWrong1*3", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }, headers:
|
18
|
+
patch password_url, params: { current_password: "SecretWrong1*3", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }, headers: default_headers
|
15
19
|
|
16
20
|
assert_response :bad_request
|
17
21
|
assert_equal "The current password you entered is incorrect", response.parsed_body["error"]
|
@@ -5,13 +5,17 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
|
|
5
5
|
@<%= singular_table_name %>, @token = sign_in_as(<%= table_name %>(:lazaro_nixon))
|
6
6
|
end
|
7
7
|
|
8
|
+
def default_headers
|
9
|
+
{ "Authorization" => "Bearer #{@token}" }
|
10
|
+
end
|
11
|
+
|
8
12
|
test "should get index" do
|
9
|
-
get sessions_url, headers:
|
13
|
+
get sessions_url, headers: default_headers
|
10
14
|
assert_response :success
|
11
15
|
end
|
12
16
|
|
13
17
|
test "should show session" do
|
14
|
-
get session_url(@<%= singular_table_name %>.sessions.last), headers:
|
18
|
+
get session_url(@<%= singular_table_name %>.sessions.last), headers: default_headers
|
15
19
|
assert_response :success
|
16
20
|
end
|
17
21
|
|
@@ -28,7 +32,7 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
|
|
28
32
|
end
|
29
33
|
|
30
34
|
test "should sign out" do
|
31
|
-
delete session_url(@<%= singular_table_name %>.sessions.last), headers:
|
35
|
+
delete session_url(@<%= singular_table_name %>.sessions.last), headers: default_headers
|
32
36
|
assert_response :no_content
|
33
37
|
end
|
34
38
|
end
|
@@ -10,22 +10,15 @@ class Identity::EmailsControllerTest < ActionDispatch::IntegrationTest
|
|
10
10
|
assert_response :success
|
11
11
|
end
|
12
12
|
|
13
|
-
test "should not get edit without sudo" do
|
14
|
-
@<%= singular_table_name %>.sessions.last.update! sudo_at: 1.day.ago
|
15
|
-
|
16
|
-
get edit_identity_email_url
|
17
|
-
assert_redirected_to new_sessions_sudo_url(proceed_to_url: edit_identity_email_url)
|
18
|
-
end
|
19
|
-
|
20
13
|
test "should update email" do
|
21
|
-
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*" }
|
22
15
|
assert_redirected_to root_url
|
23
16
|
end
|
24
17
|
|
25
|
-
test "should not update email
|
26
|
-
|
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" }
|
27
20
|
|
28
|
-
|
29
|
-
|
21
|
+
assert_redirected_to edit_identity_email_url
|
22
|
+
assert_equal "The password you entered is incorrect", flash[:alert]
|
30
23
|
end
|
31
24
|
end
|
@@ -6,9 +6,6 @@ class Identity::PasswordResetsControllerTest < ActionDispatch::IntegrationTest
|
|
6
6
|
@sid = @<%= singular_table_name %>.signed_id(purpose: :password_reset, expires_in: 20.minutes)
|
7
7
|
@sid_exp = @<%= singular_table_name %>.signed_id(purpose: :password_reset, expires_in: 0.minutes)
|
8
8
|
end
|
9
|
-
<% if options.lockable? %>
|
10
|
-
teardown { Kredis.clear_all }
|
11
|
-
<% end -%>
|
12
9
|
|
13
10
|
test "should get new" do
|
14
11
|
get new_identity_password_reset_url
|
data/lib/generators/authentication/templates/test_unit/system/identity/password_resets_test.rb.tt
CHANGED
@@ -5,9 +5,6 @@ class Identity::PasswordResetsTest < ApplicationSystemTestCase
|
|
5
5
|
@<%= singular_table_name %> = <%= table_name %>(:lazaro_nixon)
|
6
6
|
@sid = @<%= singular_table_name %>.signed_id(purpose: :password_reset, expires_in: 20.minutes)
|
7
7
|
end
|
8
|
-
<% if options.lockable? %>
|
9
|
-
teardown { Kredis.clear_all }
|
10
|
-
<% end -%>
|
11
8
|
|
12
9
|
test "sending a password reset email" do
|
13
10
|
visit sign_in_url
|
@@ -10,13 +10,13 @@ class ActiveSupport::TestCase
|
|
10
10
|
fixtures :all
|
11
11
|
|
12
12
|
# Add more helper methods to be used by all tests here...
|
13
|
-
|
13
|
+
<%- if options.api? -%>
|
14
14
|
def sign_in_as(<%= singular_table_name %>)
|
15
15
|
post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }); [<%= singular_table_name %>, response.headers["X-Session-Token"]]
|
16
16
|
end
|
17
|
-
|
17
|
+
<%- else -%>
|
18
18
|
def sign_in_as(<%= singular_table_name %>)
|
19
19
|
post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }); <%= singular_table_name %>
|
20
20
|
end
|
21
|
-
|
21
|
+
<%- end -%>
|
22
22
|
end
|
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.
|
4
|
+
version: 2.11.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nixon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-03-
|
11
|
+
date: 2022-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -19,6 +19,7 @@ extra_rdoc_files: []
|
|
19
19
|
files:
|
20
20
|
- ".github/FUNDING.yml"
|
21
21
|
- ".gitignore"
|
22
|
+
- ".rubocop.yml"
|
22
23
|
- CHANGELOG.md
|
23
24
|
- CODE_OF_CONDUCT.md
|
24
25
|
- Gemfile
|
@@ -54,6 +55,8 @@ files:
|
|
54
55
|
- lib/generators/authentication/templates/controllers/html/sessions/omniauth_controller.rb.tt
|
55
56
|
- lib/generators/authentication/templates/controllers/html/sessions/sudos_controller.rb.tt
|
56
57
|
- lib/generators/authentication/templates/controllers/html/sessions_controller.rb.tt
|
58
|
+
- lib/generators/authentication/templates/controllers/html/two_factor_authentication/challenges_controller.rb.tt
|
59
|
+
- lib/generators/authentication/templates/controllers/html/two_factor_authentication/totps_controller.rb.tt
|
57
60
|
- lib/generators/authentication/templates/erb/authentications/events/index.html.erb
|
58
61
|
- lib/generators/authentication/templates/erb/identity/emails/edit.html.erb.tt
|
59
62
|
- lib/generators/authentication/templates/erb/identity/password_resets/edit.html.erb.tt
|
@@ -69,6 +72,8 @@ files:
|
|
69
72
|
- lib/generators/authentication/templates/erb/sessions/index.html.erb.tt
|
70
73
|
- lib/generators/authentication/templates/erb/sessions/new.html.erb.tt
|
71
74
|
- lib/generators/authentication/templates/erb/sessions/sudos/new.html.erb.tt
|
75
|
+
- lib/generators/authentication/templates/erb/two_factor_authentication/challenges/new.html.erb.tt
|
76
|
+
- lib/generators/authentication/templates/erb/two_factor_authentication/totps/new.html.erb.tt
|
72
77
|
- lib/generators/authentication/templates/mailers/identity_mailer.rb.tt
|
73
78
|
- lib/generators/authentication/templates/mailers/session_mailer.rb.tt
|
74
79
|
- lib/generators/authentication/templates/migrations/create_events_migration.rb.tt
|
@@ -85,21 +90,18 @@ files:
|
|
85
90
|
- lib/generators/authentication/templates/test_unit/controllers/api/identity/password_resets_controller_test.rb.tt
|
86
91
|
- lib/generators/authentication/templates/test_unit/controllers/api/passwords_controller_test.rb.tt
|
87
92
|
- lib/generators/authentication/templates/test_unit/controllers/api/registrations_controller_test.rb.tt
|
88
|
-
- lib/generators/authentication/templates/test_unit/controllers/api/sessions/sudos_controller_test.rb.tt
|
89
93
|
- lib/generators/authentication/templates/test_unit/controllers/api/sessions_controller_test.rb.tt
|
90
94
|
- lib/generators/authentication/templates/test_unit/controllers/html/identity/email_verifications_controller_test.rb.tt
|
91
95
|
- lib/generators/authentication/templates/test_unit/controllers/html/identity/emails_controller_test.rb.tt
|
92
96
|
- lib/generators/authentication/templates/test_unit/controllers/html/identity/password_resets_controller_test.rb.tt
|
93
97
|
- lib/generators/authentication/templates/test_unit/controllers/html/passwords_controller_test.rb.tt
|
94
98
|
- lib/generators/authentication/templates/test_unit/controllers/html/registrations_controller_test.rb.tt
|
95
|
-
- lib/generators/authentication/templates/test_unit/controllers/html/sessions/sudos_controller_test.rb.tt
|
96
99
|
- lib/generators/authentication/templates/test_unit/controllers/html/sessions_controller_test.rb.tt
|
97
100
|
- lib/generators/authentication/templates/test_unit/fixtures.yml.tt
|
98
101
|
- lib/generators/authentication/templates/test_unit/system/identity/emails_test.rb.tt
|
99
102
|
- lib/generators/authentication/templates/test_unit/system/identity/password_resets_test.rb.tt
|
100
103
|
- lib/generators/authentication/templates/test_unit/system/passwords_test.rb.tt
|
101
104
|
- lib/generators/authentication/templates/test_unit/system/registrations_test.rb.tt
|
102
|
-
- lib/generators/authentication/templates/test_unit/system/sessions/sudos_test.rb.tt
|
103
105
|
- lib/generators/authentication/templates/test_unit/system/sessions_test.rb.tt
|
104
106
|
- lib/generators/authentication/templates/test_unit/test_helper.rb.tt
|
105
107
|
homepage: https://github.com/lazaronixon/authentication-zero
|
@@ -1,20 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class Sessions::SudosControllerTest < ActionDispatch::IntegrationTest
|
4
|
-
setup do
|
5
|
-
@<%= singular_table_name %>, @token = sign_in_as(<%= table_name %>(:lazaro_nixon))
|
6
|
-
@<%= singular_table_name %>.sessions.last.update! sudo_at: 1.day.ago
|
7
|
-
end
|
8
|
-
|
9
|
-
test "should sudo" do
|
10
|
-
post sessions_sudo_url, params: { password: "Secret1*3*5*" }, headers: { "Authorization" => "Bearer #{@token}" }
|
11
|
-
assert_response :no_content
|
12
|
-
end
|
13
|
-
|
14
|
-
test "should not sudo with wrong password" do
|
15
|
-
post sessions_sudo_url, params: { password: "SecretWrong1*3" }, headers: { "Authorization" => "Bearer #{@token}" }
|
16
|
-
|
17
|
-
assert_response :bad_request
|
18
|
-
assert_equal "The password you entered is incorrect", response.parsed_body["error"]
|
19
|
-
end
|
20
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class Sessions::SudosControllerTest < ActionDispatch::IntegrationTest
|
4
|
-
setup do
|
5
|
-
@<%= singular_table_name %> = sign_in_as(<%= table_name %>(:lazaro_nixon))
|
6
|
-
end
|
7
|
-
|
8
|
-
test "should get new" do
|
9
|
-
get new_sessions_sudo_url(proceed_to_url: edit_password_url)
|
10
|
-
assert_response :success
|
11
|
-
end
|
12
|
-
|
13
|
-
test "should sudo" do
|
14
|
-
post sessions_sudo_url, params: { password: "Secret1*3*5*", proceed_to_url: edit_password_url }
|
15
|
-
assert_redirected_to edit_password_url
|
16
|
-
end
|
17
|
-
|
18
|
-
test "should not sudo with wrong password" do
|
19
|
-
post sessions_sudo_url, params: { password: "SecretWrong1*3", proceed_to_url: edit_password_url }
|
20
|
-
assert_redirected_to new_sessions_sudo_url(proceed_to_url: edit_password_url)
|
21
|
-
end
|
22
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require "application_system_test_case"
|
2
|
-
|
3
|
-
class Sessions::SudosTest < ApplicationSystemTestCase
|
4
|
-
setup do
|
5
|
-
@<%= singular_table_name %> = sign_in_as(<%= table_name %>(:lazaro_nixon))
|
6
|
-
end
|
7
|
-
|
8
|
-
test "executing sudo" do
|
9
|
-
visit new_sessions_sudo_url(proceed_to_url: edit_password_url)
|
10
|
-
fill_in :password, with: "Secret1*3*5*"
|
11
|
-
click_on "Continue"
|
12
|
-
|
13
|
-
assert_selector "h1", text: "Change your password"
|
14
|
-
end
|
15
|
-
end
|