rodauth 2.36.0 → 2.37.0
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/lib/rodauth/features/base.rb +15 -1
- data/lib/rodauth/features/change_login.rb +2 -2
- data/lib/rodauth/features/create_account.rb +2 -2
- data/lib/rodauth/features/email_auth.rb +1 -1
- data/lib/rodauth/features/internal_request.rb +4 -4
- data/lib/rodauth/features/json.rb +5 -0
- data/lib/rodauth/features/jwt.rb +5 -9
- data/lib/rodauth/features/lockout.rb +1 -1
- data/lib/rodauth/features/login.rb +1 -1
- data/lib/rodauth/features/login_password_requirements_base.rb +13 -0
- data/lib/rodauth/features/reset_password.rb +1 -1
- data/lib/rodauth/features/two_factor_base.rb +6 -13
- data/lib/rodauth/features/verify_account.rb +2 -2
- data/lib/rodauth/features/webauthn_autofill.rb +2 -1
- data/lib/rodauth/features/webauthn_login.rb +1 -1
- data/lib/rodauth/version.rb +1 -1
- data/lib/rodauth.rb +6 -2
- metadata +3 -258
- data/CHANGELOG +0 -521
- data/README.rdoc +0 -1555
- data/doc/account_expiration.rdoc +0 -41
- data/doc/active_sessions.rdoc +0 -56
- data/doc/argon2.rdoc +0 -54
- data/doc/audit_logging.rdoc +0 -44
- data/doc/base.rdoc +0 -123
- data/doc/change_login.rdoc +0 -25
- data/doc/change_password.rdoc +0 -26
- data/doc/change_password_notify.rdoc +0 -14
- data/doc/close_account.rdoc +0 -26
- data/doc/confirm_password.rdoc +0 -32
- data/doc/create_account.rdoc +0 -27
- data/doc/disallow_common_passwords.rdoc +0 -17
- data/doc/disallow_password_reuse.rdoc +0 -30
- data/doc/email_auth.rdoc +0 -55
- data/doc/email_base.rdoc +0 -18
- data/doc/error_reasons.rdoc +0 -77
- data/doc/guides/admin_activation.rdoc +0 -46
- data/doc/guides/already_authenticated.rdoc +0 -10
- data/doc/guides/alternative_login.rdoc +0 -46
- data/doc/guides/change_table_and_column_names.rdoc +0 -19
- data/doc/guides/create_account_programmatically.rdoc +0 -38
- data/doc/guides/delay_password.rdoc +0 -25
- data/doc/guides/email_only.rdoc +0 -16
- data/doc/guides/i18n.rdoc +0 -29
- data/doc/guides/internals.rdoc +0 -233
- data/doc/guides/links.rdoc +0 -12
- data/doc/guides/login_return.rdoc +0 -37
- data/doc/guides/migrate_password_hash_algorithm.rdoc +0 -15
- data/doc/guides/password_column.rdoc +0 -25
- data/doc/guides/password_confirmation.rdoc +0 -37
- data/doc/guides/password_requirements.rdoc +0 -43
- data/doc/guides/paths.rdoc +0 -51
- data/doc/guides/query_params.rdoc +0 -9
- data/doc/guides/redirects.rdoc +0 -17
- data/doc/guides/registration_field.rdoc +0 -68
- data/doc/guides/render_confirmation.rdoc +0 -17
- data/doc/guides/require_mfa.rdoc +0 -30
- data/doc/guides/reset_password_autologin.rdoc +0 -21
- data/doc/guides/share_configuration.rdoc +0 -34
- data/doc/guides/status_column.rdoc +0 -28
- data/doc/guides/totp_or_recovery.rdoc +0 -16
- data/doc/http_basic_auth.rdoc +0 -18
- data/doc/internal_request.rdoc +0 -539
- data/doc/json.rdoc +0 -56
- data/doc/jwt.rdoc +0 -52
- data/doc/jwt_cors.rdoc +0 -22
- data/doc/jwt_refresh.rdoc +0 -58
- data/doc/lockout.rdoc +0 -73
- data/doc/login.rdoc +0 -39
- data/doc/login_password_requirements_base.rdoc +0 -44
- data/doc/logout.rdoc +0 -22
- data/doc/otp.rdoc +0 -93
- data/doc/otp_lockout_email.rdoc +0 -30
- data/doc/otp_modify_email.rdoc +0 -19
- data/doc/otp_unlock.rdoc +0 -58
- data/doc/password_complexity.rdoc +0 -34
- data/doc/password_expiration.rdoc +0 -38
- data/doc/password_grace_period.rdoc +0 -24
- data/doc/password_pepper.rdoc +0 -52
- data/doc/path_class_methods.rdoc +0 -10
- data/doc/recovery_codes.rdoc +0 -61
- data/doc/release_notes/1.0.0.txt +0 -443
- data/doc/release_notes/1.1.0.txt +0 -8
- data/doc/release_notes/1.10.0.txt +0 -80
- data/doc/release_notes/1.11.0.txt +0 -32
- data/doc/release_notes/1.12.0.txt +0 -61
- data/doc/release_notes/1.13.0.txt +0 -34
- data/doc/release_notes/1.14.0.txt +0 -19
- data/doc/release_notes/1.15.0.txt +0 -21
- data/doc/release_notes/1.16.0.txt +0 -31
- data/doc/release_notes/1.17.0.txt +0 -23
- data/doc/release_notes/1.18.0.txt +0 -26
- data/doc/release_notes/1.19.0.txt +0 -116
- data/doc/release_notes/1.2.0.txt +0 -18
- data/doc/release_notes/1.20.0.txt +0 -175
- data/doc/release_notes/1.21.0.txt +0 -12
- data/doc/release_notes/1.22.0.txt +0 -11
- data/doc/release_notes/1.23.0.txt +0 -32
- data/doc/release_notes/1.3.0.txt +0 -21
- data/doc/release_notes/1.4.0.txt +0 -11
- data/doc/release_notes/1.5.0.txt +0 -74
- data/doc/release_notes/1.6.0.txt +0 -37
- data/doc/release_notes/1.7.0.txt +0 -6
- data/doc/release_notes/1.8.0.txt +0 -14
- data/doc/release_notes/1.9.0.txt +0 -15
- data/doc/release_notes/2.0.0.txt +0 -361
- data/doc/release_notes/2.1.0.txt +0 -31
- data/doc/release_notes/2.10.0.txt +0 -47
- data/doc/release_notes/2.11.0.txt +0 -31
- data/doc/release_notes/2.12.0.txt +0 -17
- data/doc/release_notes/2.13.0.txt +0 -19
- data/doc/release_notes/2.14.0.txt +0 -17
- data/doc/release_notes/2.15.0.txt +0 -48
- data/doc/release_notes/2.16.0.txt +0 -20
- data/doc/release_notes/2.17.0.txt +0 -10
- data/doc/release_notes/2.18.0.txt +0 -27
- data/doc/release_notes/2.19.0.txt +0 -61
- data/doc/release_notes/2.2.0.txt +0 -39
- data/doc/release_notes/2.20.0.txt +0 -10
- data/doc/release_notes/2.21.0.txt +0 -28
- data/doc/release_notes/2.22.0.txt +0 -43
- data/doc/release_notes/2.23.0.txt +0 -15
- data/doc/release_notes/2.24.0.txt +0 -15
- data/doc/release_notes/2.25.0.txt +0 -8
- data/doc/release_notes/2.26.0.txt +0 -45
- data/doc/release_notes/2.27.0.txt +0 -35
- data/doc/release_notes/2.28.0.txt +0 -16
- data/doc/release_notes/2.29.0.txt +0 -27
- data/doc/release_notes/2.3.0.txt +0 -37
- data/doc/release_notes/2.30.0.txt +0 -15
- data/doc/release_notes/2.31.0.txt +0 -47
- data/doc/release_notes/2.32.0.txt +0 -65
- data/doc/release_notes/2.33.0.txt +0 -18
- data/doc/release_notes/2.34.0.txt +0 -36
- data/doc/release_notes/2.35.0.txt +0 -22
- data/doc/release_notes/2.36.0.txt +0 -35
- data/doc/release_notes/2.4.0.txt +0 -22
- data/doc/release_notes/2.5.0.txt +0 -20
- data/doc/release_notes/2.6.0.txt +0 -37
- data/doc/release_notes/2.7.0.txt +0 -33
- data/doc/release_notes/2.8.0.txt +0 -20
- data/doc/release_notes/2.9.0.txt +0 -21
- data/doc/remember.rdoc +0 -79
- data/doc/reset_password.rdoc +0 -66
- data/doc/reset_password_notify.rdoc +0 -17
- data/doc/session_expiration.rdoc +0 -28
- data/doc/single_session.rdoc +0 -37
- data/doc/sms_codes.rdoc +0 -138
- data/doc/two_factor_base.rdoc +0 -70
- data/doc/update_password_hash.rdoc +0 -7
- data/doc/verify_account.rdoc +0 -67
- data/doc/verify_account_grace_period.rdoc +0 -19
- data/doc/verify_login_change.rdoc +0 -59
- data/doc/webauthn.rdoc +0 -118
- data/doc/webauthn_autofill.rdoc +0 -19
- data/doc/webauthn_login.rdoc +0 -16
- data/doc/webauthn_modify_email.rdoc +0 -19
- data/doc/webauthn_verify_account.rdoc +0 -9
data/doc/error_reasons.rdoc
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
= Error Reasons
|
2
|
-
|
3
|
-
Rodauth allows for customizing response status codes and error
|
4
|
-
messages for each type of error. However, in some cases, the
|
5
|
-
response status code is too coarse for desired error handling
|
6
|
-
by the application (since many error types use the same status
|
7
|
-
code), and using the error message is too fragile since it may
|
8
|
-
be translated.
|
9
|
-
|
10
|
-
For this reason, Rodauth associates a fine grained reason for
|
11
|
-
each type of error. If an error occurs in Rodauth, it will
|
12
|
-
call the +set_error_reason+ method with a symbol for the
|
13
|
-
specific type of error. By default, this method does not do
|
14
|
-
anything, but you can use the +set_error_reason+ configuration
|
15
|
-
method to customize the error handling.
|
16
|
-
|
17
|
-
These are the currently supported error type symbols that
|
18
|
-
Rodauth will call +set_error_reason+ with:
|
19
|
-
|
20
|
-
* :account_locked_out
|
21
|
-
* :already_an_account_with_this_login
|
22
|
-
* :already_an_unverified_account_with_this_login
|
23
|
-
* :duplicate_webauthn_id
|
24
|
-
* :inactive_session
|
25
|
-
* :invalid_email_auth_key
|
26
|
-
* :invalid_otp_auth_code
|
27
|
-
* :invalid_otp_secret
|
28
|
-
* :invalid_password
|
29
|
-
* :invalid_password_pattern
|
30
|
-
* :invalid_phone_number
|
31
|
-
* :invalid_previous_password
|
32
|
-
* :invalid_recovery_code
|
33
|
-
* :invalid_remember_param
|
34
|
-
* :invalid_reset_password_key
|
35
|
-
* :invalid_sms_code
|
36
|
-
* :invalid_sms_confirmation_code
|
37
|
-
* :invalid_unlock_account_key
|
38
|
-
* :invalid_verify_account_key
|
39
|
-
* :invalid_verify_login_change_key
|
40
|
-
* :invalid_webauthn_auth_param
|
41
|
-
* :invalid_webauthn_id
|
42
|
-
* :invalid_webauthn_remove_param
|
43
|
-
* :invalid_webauthn_setup_param
|
44
|
-
* :invalid_webauthn_sign_count
|
45
|
-
* :login_not_valid_email
|
46
|
-
* :login_required
|
47
|
-
* :login_too_long
|
48
|
-
* :login_too_many_bytes
|
49
|
-
* :login_too_short
|
50
|
-
* :logins_do_not_match
|
51
|
-
* :no_current_sms_code
|
52
|
-
* :no_matching_login
|
53
|
-
* :not_enough_character_groups_in_password
|
54
|
-
* :otp_locked_out
|
55
|
-
* :password_authentication_required
|
56
|
-
* :password_contains_null_byte
|
57
|
-
* :password_does_not_meet_requirements
|
58
|
-
* :password_in_dictionary
|
59
|
-
* :password_is_one_of_the_most_common
|
60
|
-
* :password_same_as_previous_password
|
61
|
-
* :password_too_long
|
62
|
-
* :password_too_many_bytes
|
63
|
-
* :password_too_short
|
64
|
-
* :passwords_do_not_match
|
65
|
-
* :same_as_current_login
|
66
|
-
* :same_as_existing_password
|
67
|
-
* :session_expired
|
68
|
-
* :sms_already_setup
|
69
|
-
* :sms_locked_out
|
70
|
-
* :sms_needs_confirmation
|
71
|
-
* :sms_not_setup
|
72
|
-
* :too_many_repeating_characters_in_password
|
73
|
-
* :two_factor_already_authenticated
|
74
|
-
* :two_factor_need_authentication
|
75
|
-
* :two_factor_not_setup
|
76
|
-
* :unverified_account
|
77
|
-
* :webauthn_not_setup
|
@@ -1,46 +0,0 @@
|
|
1
|
-
= Require account verification by admin
|
2
|
-
|
3
|
-
There are scenarios in which, instead of allowing the user to verify they have
|
4
|
-
access to the email for the account, you may want to have an admin or moderator
|
5
|
-
approve new accounts manually. One way this can be achieved by sending the
|
6
|
-
account verification email to the admin:
|
7
|
-
|
8
|
-
plugin :rodauth do
|
9
|
-
enable :login, :logout, :verify_account, :reset_password
|
10
|
-
|
11
|
-
# Send account verification email to the admin
|
12
|
-
email_to do
|
13
|
-
if account[account_status_column] == account_unverified_status_value
|
14
|
-
"admin@myapp.com"
|
15
|
-
else
|
16
|
-
super()
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# Do not ask for password when creating or verifying account
|
21
|
-
verify_account_set_password? false
|
22
|
-
create_account_set_password? false
|
23
|
-
|
24
|
-
# Adjust the account verification email subject and body
|
25
|
-
verify_account_email_subject "New User Awaiting Admin Approval"
|
26
|
-
verify_account_email_body do
|
27
|
-
"The user #{account[login_column]} has created an account. Click here to approve it: #{verify_account_email_link}."
|
28
|
-
end
|
29
|
-
|
30
|
-
# Display this message to the user after they've created their account
|
31
|
-
verify_account_email_sent_notice_flash "Your account has been created and is awaiting approval"
|
32
|
-
|
33
|
-
# Prevent the admin from being logged in after confirming the account
|
34
|
-
verify_account_autologin? false
|
35
|
-
verify_account_notice_flash "The account has been approved"
|
36
|
-
|
37
|
-
# Send a reset password email after verifying the account.
|
38
|
-
# This allows the user to choose the password for the account,
|
39
|
-
# and also makes sure the user can only log in if they have
|
40
|
-
# access to the email address for the account.
|
41
|
-
after_verify_account do
|
42
|
-
generate_reset_password_key_value
|
43
|
-
create_reset_password_key
|
44
|
-
send_reset_password_email
|
45
|
-
end
|
46
|
-
end
|
@@ -1,10 +0,0 @@
|
|
1
|
-
= Skip login page if already authenticated
|
2
|
-
|
3
|
-
In some cases it may be useful to skip login/registration pages when the user
|
4
|
-
is already logged in. This can be achieved as follows. Note that this only
|
5
|
-
matters if the user manually navigates to the login or create account pages.
|
6
|
-
|
7
|
-
plugin :rodauth do
|
8
|
-
# Redirect logged in users to the wherever login redirects to
|
9
|
-
already_logged_in { redirect login_redirect }
|
10
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
= Use a non-email login
|
2
|
-
|
3
|
-
Rodauth's by default uses email addresses for identifying users, since that is
|
4
|
-
the most common form of identifier currently. In some cases, you might want
|
5
|
-
to allow logging in via alternative identifiers, such as a username. In this
|
6
|
-
case, it is best to choose a different column name for the login, such as
|
7
|
-
+:username+. Among other things, this also makes it so that the login field
|
8
|
-
does not expect an email address to be provided.
|
9
|
-
|
10
|
-
plugin :rodauth do
|
11
|
-
enable :login, :logout
|
12
|
-
login_column :username
|
13
|
-
end
|
14
|
-
|
15
|
-
Note that Rodauth features that require sending email need an email address, and
|
16
|
-
that defaults to the value of the login column. If you have both a username and
|
17
|
-
an email for an account, you can have the login column be the user, and use the
|
18
|
-
value of the email colummn for the email address.
|
19
|
-
|
20
|
-
plugin :rodauth do
|
21
|
-
enable :login, :logout, :reset_password
|
22
|
-
|
23
|
-
login_column :username
|
24
|
-
email_to do
|
25
|
-
account[:email]
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
An alternative approach would be to accept a login and automatically change it
|
30
|
-
to an email address. If you have a +username+ field on the +accounts+ table,
|
31
|
-
then you can configure Rodauth to allow entering a username instead of email
|
32
|
-
during login. See the {Adding new registration field}[rdoc-ref:doc/guides/registration_field.rdoc]
|
33
|
-
guide for instructions on requiring add an additional field during registration.
|
34
|
-
|
35
|
-
plugin :rodauth do
|
36
|
-
enable :login, :logout
|
37
|
-
|
38
|
-
account_from_login do |login|
|
39
|
-
# handle the case when login parameter is a username
|
40
|
-
unless login.include?("@")
|
41
|
-
login = db[:accounts].where(username: login).get(:email)
|
42
|
-
end
|
43
|
-
|
44
|
-
super(login)
|
45
|
-
end
|
46
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
= Change table and column names
|
2
|
-
|
3
|
-
All tables that Rodauth uses will have a configuration method that ends with
|
4
|
-
+_table+ for configuring the table name. For example, if you store user accounts
|
5
|
-
in the +users+ table instead of +accounts+ table, you can use the following
|
6
|
-
in your configuration:
|
7
|
-
|
8
|
-
accounts_table :users
|
9
|
-
|
10
|
-
All columns that Rodauth uses will have a configuration method that ends with
|
11
|
-
+_column+ for configuring the column name. For example, if you are storing the
|
12
|
-
login for accounts in the +login+ column instead of the +email+ column, you
|
13
|
-
can use the following in your configuration:
|
14
|
-
|
15
|
-
login_column :login
|
16
|
-
|
17
|
-
Please see the documentation for Rodauth features for the names of the
|
18
|
-
configuration methods that you can use. You can see the default values for
|
19
|
-
the tables and columns in the {"Creating tables" section of the README}[rdoc-ref:README.rdoc].
|
@@ -1,38 +0,0 @@
|
|
1
|
-
= Create an account record programmatically
|
2
|
-
|
3
|
-
In some scenarios you might want to create an account records programmatically,
|
4
|
-
for example in your tests.
|
5
|
-
|
6
|
-
If you're storing passwords in a separate table, you can create an account
|
7
|
-
records as follows:
|
8
|
-
|
9
|
-
account_id = DB[:accounts].insert(
|
10
|
-
email: "name@example.com",
|
11
|
-
status_id: 2, # verified
|
12
|
-
)
|
13
|
-
|
14
|
-
DB[:account_password_hashes].insert(
|
15
|
-
id: account_id,
|
16
|
-
password_hash: BCrypt::Password.create("secret").to_s,
|
17
|
-
)
|
18
|
-
|
19
|
-
If the password is stored in a column in the accounts table:
|
20
|
-
|
21
|
-
account_id = DB[:accounts].insert(
|
22
|
-
email: "name@example.com",
|
23
|
-
password_hash: BCrypt::Password.create("secret").to_s,
|
24
|
-
status_id: 2, # verified
|
25
|
-
)
|
26
|
-
|
27
|
-
If you are creating accounts in your tests, you probably want to use
|
28
|
-
the +:cost+ option, otherwise you will have very slow tests:
|
29
|
-
|
30
|
-
account_id = DB[:accounts].insert(
|
31
|
-
email: "name@example.com",
|
32
|
-
status_id: 2, # verified
|
33
|
-
)
|
34
|
-
|
35
|
-
DB[:account_password_hashes].insert(
|
36
|
-
id: account_id,
|
37
|
-
password_hash: BCrypt::Password.create("secret", cost: BCrypt::Engine::MIN_COST).to_s,
|
38
|
-
)
|
@@ -1,25 +0,0 @@
|
|
1
|
-
= Set password when verifying account
|
2
|
-
|
3
|
-
If you want to request less information from the user on registration, you can
|
4
|
-
ask the user to set their password only when they verify their account:
|
5
|
-
|
6
|
-
plugin :rodauth do
|
7
|
-
enable :login, :logout, :verify_account
|
8
|
-
verify_account_set_password? true
|
9
|
-
end
|
10
|
-
|
11
|
-
Note that this is already the default behaviour when verify account feature is
|
12
|
-
loaded, but it's not when verify account grace period is used, because it would
|
13
|
-
prevent the account from logging in during the grace period. You can work around
|
14
|
-
this by automatically remebering their login during account creation using the
|
15
|
-
remember feature. Be aware that remembering accounts has effects beyond the
|
16
|
-
verification period, and this would only allow automatic logins from the browser
|
17
|
-
that created the account.
|
18
|
-
|
19
|
-
plugin :rodauth do
|
20
|
-
enable :login, :logout, :verify_account_grace_period, :remember
|
21
|
-
verify_account_set_password? true
|
22
|
-
after_create_account do
|
23
|
-
remember_login
|
24
|
-
end
|
25
|
-
end
|
data/doc/guides/email_only.rdoc
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
= Allow only email authentication
|
2
|
-
|
3
|
-
When using the email authentication feature, you can avoid other authentication
|
4
|
-
mechanisms entirely as follows:
|
5
|
-
|
6
|
-
plugin :rodauth do
|
7
|
-
enable :login, :email_auth, :create_account, :verify_account
|
8
|
-
|
9
|
-
create_account_set_password? false
|
10
|
-
verify_account_set_password? false
|
11
|
-
force_email_auth? true
|
12
|
-
end
|
13
|
-
|
14
|
-
With this configuration, users won't be required to enter a password on
|
15
|
-
registration, and on login the email authentication link will automatically be
|
16
|
-
sent after the email address is entered.
|
data/doc/guides/i18n.rdoc
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
= Translate with i18n gem
|
2
|
-
|
3
|
-
Rodauth allows transforming user-facing text configuration such as flash
|
4
|
-
messages, validation errors, labels etc. via the +translate+ configuration
|
5
|
-
method. This method receives a name of a configuration along with its default
|
6
|
-
value, and is expected to return the result text.
|
7
|
-
|
8
|
-
You can use this to perform translations using the
|
9
|
-
{i18n gem}[https://github.com/ruby-i18n/i18n]:
|
10
|
-
|
11
|
-
plugin :rodauth do
|
12
|
-
enable :login, :logout, :reset_password
|
13
|
-
|
14
|
-
translate do |key, default|
|
15
|
-
I18n.translate("rodauth.#{key}") || default
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
Your translation file may then look something like this:
|
20
|
-
|
21
|
-
en:
|
22
|
-
rodauth:
|
23
|
-
login_notice_flash: "You have been signed in"
|
24
|
-
require_login_error_flash: "Login is required for accessing this page"
|
25
|
-
no_matching_login_message: "user with this email address doesn't exist"
|
26
|
-
reset_password_email_subject: "Password Reset Instructions"
|
27
|
-
|
28
|
-
Alternatively, you can use the
|
29
|
-
{rodauth-i18n}[https://github.com/janko/rodauth-i18n] gem.
|
data/doc/guides/internals.rdoc
DELETED
@@ -1,233 +0,0 @@
|
|
1
|
-
= Rodauth Internals
|
2
|
-
|
3
|
-
Rodauth's implementation heavily uses metaprogramming in order to DRY up the codebase, which can be a little intimidating to developers who are not familiar with the codebase. This guide explains how Rodauth is built, which should make the internals easier to understand.
|
4
|
-
|
5
|
-
== Object Model
|
6
|
-
|
7
|
-
First, let's talk about the basic parts of Rodauth.
|
8
|
-
|
9
|
-
=== Rodauth::Auth
|
10
|
-
|
11
|
-
Rodauth::Auth is the core of rodauth. If a user calls +rodauth+ inside their Roda application, they get a Rodauth::Auth subclass instance. Rodauth's configuration DSL is designed to build a Rodauth::Auth subclass appropriate to the application, by loading only the features that are needed, and overriding defaults as appropriate.
|
12
|
-
|
13
|
-
=== Rodauth::Configuration
|
14
|
-
|
15
|
-
Inside the block you pass to <tt>plugin :rodauth</tt>, +self+ is an instance of this class. This class is mostly empty, as most of Rodauth is implemented as separate features, and the configuration for each feature is loaded as a separate module into this instance.
|
16
|
-
|
17
|
-
=== Rodauth::Feature
|
18
|
-
|
19
|
-
Each of the parts of rodauth that you can use is going to be a separate feature. Rodauth::Feature is a Module subclass, and every rodauth feature you load is an instance of this class, which is included in the Rodauth::Auth subclass used by the Roda application. Rodauth::Feature has many methods designed to make building Rodauth features easier by defining methods in the Rodauth::Feature instance.
|
20
|
-
|
21
|
-
=== Rodauth::FeatureConfiguration
|
22
|
-
|
23
|
-
Just as each feature is a module included in the Rodauth::Auth subclass for the application, each feature also contains a configuration module that is an instance of Rodauth::FeatureConfiguration (also a module subclass). For each feature you load into the Rodauth configuration, the Rodauth::Configuration instance is extended with the feature's Rodauth::FeatureConfiguration instance, which is what makes the feature's configuration methods available inside the <tt>plugin :rodauth</tt> block. This is why you need to enable the features in Rodauth before configuring them.
|
24
|
-
|
25
|
-
|
26
|
-
== Object Model Example
|
27
|
-
|
28
|
-
Here's some commented output hopefully showing the relation between the different parts
|
29
|
-
|
30
|
-
Roda.plugin :rodauth do
|
31
|
-
self # => #<Rodauth::Configuration> (instance)
|
32
|
-
auth # => Rodauth::Auth subclass
|
33
|
-
|
34
|
-
singleton_class.ancestors # => [#<Class:#<Rodauth::Configuration>> (singleton class of self),
|
35
|
-
# Rodauth::FeatureConfiguration::Base (instance of Rodauth::FeatureConfiguration),
|
36
|
-
# Rodauth::Configuration,
|
37
|
-
# ...]
|
38
|
-
auth.ancestors # => [Rodauth::Auth subclass,
|
39
|
-
# Rodauth::Base (instance of Rodauth::Feature),
|
40
|
-
# Rodauth::Auth,
|
41
|
-
# ...]
|
42
|
-
|
43
|
-
enable :login
|
44
|
-
|
45
|
-
singleton_class.ancestors # => [#<Class:#<Rodauth::Configuration>> (singleton class of self),
|
46
|
-
# Rodauth::FeatureConfiguration::Login (instance of Rodauth::FeatureConfiguration),
|
47
|
-
# Rodauth::FeatureConfiguration::Base (instance of Rodauth::FeatureConfiguration),
|
48
|
-
# Rodauth::Configuration,
|
49
|
-
# ...]
|
50
|
-
auth.ancestors # => [Rodauth::Auth subclass,
|
51
|
-
# Rodauth::Login (instance of Rodauth::Feature),
|
52
|
-
# Rodauth::Base (instance of Rodauth::Feature),
|
53
|
-
# Rodauth::Auth,
|
54
|
-
# ...]
|
55
|
-
end
|
56
|
-
|
57
|
-
Roda.rodauth # => Rodauth::Auth subclass
|
58
|
-
Roda.rodauth.ancestors # => [Rodauth::Auth subclass,
|
59
|
-
# Rodauth::Login (instance of Rodauth::Feature),
|
60
|
-
# Rodauth::Base (instance of Rodauth::Feature),
|
61
|
-
# Rodauth::Auth,
|
62
|
-
# ...]
|
63
|
-
|
64
|
-
Roda.route do |r|
|
65
|
-
rodauth # => Rodauth::Auth subclass instance
|
66
|
-
end
|
67
|
-
|
68
|
-
== Feature Creation Example
|
69
|
-
|
70
|
-
Here's a heavily commented example showing what is going on inside a Rodauth feature.
|
71
|
-
|
72
|
-
module Rodauth
|
73
|
-
# Feature.define takes a symbol, specifying the name of the feature. This
|
74
|
-
# is the same symbol you would pass to enable when loading the feature into
|
75
|
-
# the Rodauth configuration. Feature is a module subclass, and Feature.define
|
76
|
-
# is a class method that creates an instance of Feature (a module) and executes
|
77
|
-
# the block in the context of the Feature instance.
|
78
|
-
#
|
79
|
-
# The second argument is optional, and sets the Feature instance and related
|
80
|
-
# FeatureConfiguration instance to a constant in the Rodauth namespace, which
|
81
|
-
# makes it easier to locate via inspect.
|
82
|
-
Feature.define(:foo, :Foo) do
|
83
|
-
# Inside this block, self is an instance of Feature. As this instance of
|
84
|
-
# Feature will be included in the Rodauth::Auth subclass instance if
|
85
|
-
# the feature is loaded into the rodauth configuration, methods you define
|
86
|
-
# in this block (via def or define_method) will be callable on any
|
87
|
-
# rodauth object if this feature is loaded into the rodauth configuration.
|
88
|
-
|
89
|
-
# Feature has many instance methods that define methods in the Feature
|
90
|
-
# instance. This is one of those methods, which sets the text of the notice
|
91
|
-
# flash, shown after successful submission of the form. It's basically
|
92
|
-
# equivalent to executing this code in the feature:
|
93
|
-
#
|
94
|
-
# def foo_notice_flash
|
95
|
-
# "It worked!"
|
96
|
-
# end
|
97
|
-
#
|
98
|
-
# while also adding a method to the configuration which does:
|
99
|
-
#
|
100
|
-
# def foo_notice_flash(v=nil, &block)
|
101
|
-
# block ||= proc{v}
|
102
|
-
# @auth.class_eval do
|
103
|
-
# define_method(:foo_notice_flash, &block)
|
104
|
-
# end
|
105
|
-
# end
|
106
|
-
#
|
107
|
-
# This is what easily allows you to modify any part of Rodauth during
|
108
|
-
# configuration. The Rodauth::Auth subclass has the default behavior
|
109
|
-
# added via a method in an included module (the Feature instance), and the
|
110
|
-
# Rodauth::Configuration instance has a method that when called defines
|
111
|
-
# a method in the Rodauth::Auth subclass itself, which will take precedence
|
112
|
-
# over the default method, which defined in the included Feature instance.
|
113
|
-
notice_flash "It worked!"
|
114
|
-
|
115
|
-
# The rest of these method calls are fairly similar to notice_flash.
|
116
|
-
# This defines the foo_error_flash method, for the error flash message to
|
117
|
-
# show if the form submission wasn't successful.
|
118
|
-
error_flash "There was an error"
|
119
|
-
|
120
|
-
# This defines the foo_view method to use template 'foo.str' in the templates
|
121
|
-
# folder, and set the title of the page to 'Foo'.
|
122
|
-
view 'foo', 'Foo'
|
123
|
-
|
124
|
-
# This defines the foo_additional_form_tags method, which would generally be called
|
125
|
-
# inside the foo.str template.
|
126
|
-
additional_form_tags
|
127
|
-
|
128
|
-
# This defines the foo_button method, for the text to use on the submit button
|
129
|
-
# for the form in foo.str.
|
130
|
-
button 'Submit'
|
131
|
-
|
132
|
-
# This defines the foo_redirect method, for where to redirect after successful submission
|
133
|
-
# of the form.
|
134
|
-
redirect
|
135
|
-
|
136
|
-
# This defines the before_foo method, called before performing the foo action.
|
137
|
-
before
|
138
|
-
|
139
|
-
# This defines the after_foo method, called after successfully performing the foo action.
|
140
|
-
after
|
141
|
-
|
142
|
-
# This defines a loaded_templates method that calls super and adds 'foo' as one of the
|
143
|
-
# templates. This is necessary for precompilation of templates to work.
|
144
|
-
loaded_templates ['foo']
|
145
|
-
|
146
|
-
# This defines the following methods related to sending email:
|
147
|
-
#
|
148
|
-
# * foo_email_subject: uses given subject
|
149
|
-
# * foo_email_body: renders foo-email template
|
150
|
-
# * create_foo_email: creates Mail::Message using subject and body
|
151
|
-
# * send_foo_email: sends created email
|
152
|
-
#
|
153
|
-
# The foo-email template should be included in the loaded_templates call to make sure
|
154
|
-
# template precompilation works.
|
155
|
-
email :foo, 'Foo Subject'
|
156
|
-
|
157
|
-
# auth_value_method is a generic method that takes two arguments, a method to define
|
158
|
-
# and a default value. It is similar to the methods above, except that it allows
|
159
|
-
# arbitrary method names. The notice_flash, error_flash, button, and additional_form_tags
|
160
|
-
# methods are actually defined in terms of this method.
|
161
|
-
#
|
162
|
-
# So this particular method defines a foo_error_status method that will return 401 by
|
163
|
-
# default, but also adds a configuration method that allows you to override the default.
|
164
|
-
auth_value_method :foo_error_status, 401
|
165
|
-
|
166
|
-
# This is similar to auth_value_method, but it only adds the configuration method.
|
167
|
-
# Using this should only be done if you have defining the method in the feature
|
168
|
-
# separately (see below).
|
169
|
-
auth_value_methods :foo_bar
|
170
|
-
|
171
|
-
# This is similar to auth_value_methods, but it changes the configuration method so that
|
172
|
-
# a block is required and you cannot provide an argument. This is used for the cases
|
173
|
-
# where a statically defined value would never make sense, such as when any correct
|
174
|
-
# behavior would depend on accessing request-specific information.
|
175
|
-
auth_methods :foo
|
176
|
-
|
177
|
-
# route defines a route used for the feature. This is the code that will be executed
|
178
|
-
# if a user goes to /foo in the Roda app.
|
179
|
-
route do |r|
|
180
|
-
# Inside the block, you are in the context of the Rodauth::Auth subclass instance.
|
181
|
-
# r is the Roda::RodaRequest subclass instance, just as it would be for a Roda
|
182
|
-
# route block.
|
183
|
-
|
184
|
-
# route adds a before_foo_route method that by default does nothing. It also
|
185
|
-
# adds a configuration method that you can call to set behavior that will be
|
186
|
-
# executed before routing.
|
187
|
-
before_foo_route
|
188
|
-
|
189
|
-
# Just like in Roda, r.get is called for GET requests
|
190
|
-
r.get do
|
191
|
-
# This will render a view to the user, using the foo.erb template from the
|
192
|
-
# templates directory (unless the user has overridden it), inside the Roda
|
193
|
-
# application's layout.
|
194
|
-
foo_view
|
195
|
-
end
|
196
|
-
|
197
|
-
# Just like in Roda, r.post is called for POST requests
|
198
|
-
r.post do
|
199
|
-
# This is called before performing the foo action
|
200
|
-
before_foo
|
201
|
-
|
202
|
-
# This assumes foo returns false or nil on failure, or otherwise on
|
203
|
-
# success.
|
204
|
-
if foo
|
205
|
-
# In general, Rodauth only calls after_foo if foo is successful.
|
206
|
-
after_foo
|
207
|
-
|
208
|
-
# Successful form submission will usually set the notice flash,
|
209
|
-
# the redirect to the appropriate page.
|
210
|
-
set_notice_flash foo_notice_flash
|
211
|
-
redirect foo_redirect
|
212
|
-
else
|
213
|
-
# Unsucessful form subsmission will usually set the error flash,
|
214
|
-
# the redisplay the page so that the submission can be fixed.
|
215
|
-
set_error_flash foo_error_flash
|
216
|
-
foo_view
|
217
|
-
end
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
# This is the default behavior for the foo method, if a user doesn't
|
222
|
-
# call the foo method inside the configuration block.
|
223
|
-
def foo
|
224
|
-
# Do Something
|
225
|
-
end
|
226
|
-
|
227
|
-
# This is the default behavior for the foo_bar method, if a user doesn't
|
228
|
-
# call the foo_bar method inside the configuration block.
|
229
|
-
def foo_bar
|
230
|
-
42
|
231
|
-
end
|
232
|
-
end
|
233
|
-
end
|
data/doc/guides/links.rdoc
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
= Display authentication links
|
2
|
-
|
3
|
-
You can retrieve a relative URL to any Rodauth action by calling the
|
4
|
-
corresponding <tt>*_path</tt> method on the Rodauth instance:
|
5
|
-
|
6
|
-
<a href="<%= rodauth.login_path %>">Sign in</a>
|
7
|
-
<a href="<%= rodauth.create_account_path %>">Sign up</a>
|
8
|
-
|
9
|
-
For absolute URLs instead of paths, you can use the <tt>*_url</tt> methods:
|
10
|
-
|
11
|
-
<a href="<%= rodauth.login_url %>">Sign in</a>
|
12
|
-
<a href="<%= rodauth.create_account_url %>">Sign up</a>
|
@@ -1,37 +0,0 @@
|
|
1
|
-
= Redirect to original page after login
|
2
|
-
|
3
|
-
When the user attempts to open a page that requires authentication, Rodauth
|
4
|
-
redirects them to the login page. It can be useful to redirect them back to
|
5
|
-
the page they originally requested after successful login. Similarly, you
|
6
|
-
can do this for pages requiring multifactor authentication.
|
7
|
-
|
8
|
-
plugin :rodauth do
|
9
|
-
enable :login, :logout, :otp
|
10
|
-
|
11
|
-
# Have successful login redirect back to originally requested page
|
12
|
-
login_return_to_requested_location? true
|
13
|
-
|
14
|
-
# Have successful multifactor authentication redirect back to
|
15
|
-
# originally requested page
|
16
|
-
two_factor_auth_return_to_requested_location? true
|
17
|
-
end
|
18
|
-
|
19
|
-
You can manually set which page to redirect after login or multifactor
|
20
|
-
authentication, though it is questionable whether the user will desire
|
21
|
-
this behavior compared to the default.
|
22
|
-
|
23
|
-
route do |r|
|
24
|
-
r.rodauth
|
25
|
-
|
26
|
-
# Return the last visited path after login
|
27
|
-
if rodauth.logged_in?
|
28
|
-
# Return to the last visited page after multifactor authentication
|
29
|
-
unless rodauth.two_factor_authenticated?
|
30
|
-
session[rodauth.two_factor_auth_redirect_session_key] = request.fullpath
|
31
|
-
end
|
32
|
-
else
|
33
|
-
session[rodauth.login_redirect_session_key] = request.fullpath
|
34
|
-
end
|
35
|
-
|
36
|
-
# rest of routes
|
37
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
= Migrate users passwords from bcrypt to argon2 or back
|
2
|
-
|
3
|
-
If you are currently using the default bcrypt password hash algorithm, and want to
|
4
|
-
gradually migrate to the argon2 password hash algorithm, you can use both the argon2
|
5
|
-
and update_password_hash features:
|
6
|
-
|
7
|
-
plugin :rodauth do
|
8
|
-
enable :login, :update_password_hash, :argon2
|
9
|
-
end
|
10
|
-
|
11
|
-
When a user with a current bcrypt password hash next successfully uses their
|
12
|
-
password, their password hash will be migrated to argon2.
|
13
|
-
|
14
|
-
If for some reason you want to migrate back from argon2 to bcrypt, you can set
|
15
|
-
<tt>use_argon2? false</tt> in your Rodauth configuration.
|
@@ -1,25 +0,0 @@
|
|
1
|
-
= Store password hash in accounts table
|
2
|
-
|
3
|
-
By default, Rodauth stores the password hash in a separate
|
4
|
-
+account_password_hashes+ table. This makes it a lot less likely that the
|
5
|
-
password hashes will be leaked, especially if you use Rodauth's default
|
6
|
-
approach of using database functions for checking the hashes.
|
7
|
-
|
8
|
-
However, if you have reasons for storing the password hashes in +accounts+
|
9
|
-
table that outweigh the security benefits of Rodauth's default approach,
|
10
|
-
Rodauth supports that.
|
11
|
-
|
12
|
-
To do this, add the password hash column to the +accounts+ table:
|
13
|
-
|
14
|
-
alter_table :accounts do
|
15
|
-
add_column :password_hash, String
|
16
|
-
end
|
17
|
-
|
18
|
-
And then tell Rodauth to use it:
|
19
|
-
|
20
|
-
plugin :rodauth do
|
21
|
-
enable :login, :logout
|
22
|
-
|
23
|
-
# Use the password_hash column in the accounts table
|
24
|
-
account_password_hash_column :password_hash
|
25
|
-
end
|