rodauth 2.36.0 → 2.37.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|