rodauth 2.36.0 → 2.37.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rodauth/features/base.rb +15 -1
  3. data/lib/rodauth/features/change_login.rb +2 -2
  4. data/lib/rodauth/features/create_account.rb +2 -2
  5. data/lib/rodauth/features/email_auth.rb +1 -1
  6. data/lib/rodauth/features/internal_request.rb +4 -4
  7. data/lib/rodauth/features/json.rb +5 -0
  8. data/lib/rodauth/features/jwt.rb +5 -9
  9. data/lib/rodauth/features/lockout.rb +1 -1
  10. data/lib/rodauth/features/login.rb +1 -1
  11. data/lib/rodauth/features/login_password_requirements_base.rb +13 -0
  12. data/lib/rodauth/features/reset_password.rb +1 -1
  13. data/lib/rodauth/features/two_factor_base.rb +6 -13
  14. data/lib/rodauth/features/verify_account.rb +2 -2
  15. data/lib/rodauth/features/webauthn_autofill.rb +2 -1
  16. data/lib/rodauth/features/webauthn_login.rb +1 -1
  17. data/lib/rodauth/version.rb +1 -1
  18. data/lib/rodauth.rb +6 -2
  19. metadata +3 -258
  20. data/CHANGELOG +0 -521
  21. data/README.rdoc +0 -1555
  22. data/doc/account_expiration.rdoc +0 -41
  23. data/doc/active_sessions.rdoc +0 -56
  24. data/doc/argon2.rdoc +0 -54
  25. data/doc/audit_logging.rdoc +0 -44
  26. data/doc/base.rdoc +0 -123
  27. data/doc/change_login.rdoc +0 -25
  28. data/doc/change_password.rdoc +0 -26
  29. data/doc/change_password_notify.rdoc +0 -14
  30. data/doc/close_account.rdoc +0 -26
  31. data/doc/confirm_password.rdoc +0 -32
  32. data/doc/create_account.rdoc +0 -27
  33. data/doc/disallow_common_passwords.rdoc +0 -17
  34. data/doc/disallow_password_reuse.rdoc +0 -30
  35. data/doc/email_auth.rdoc +0 -55
  36. data/doc/email_base.rdoc +0 -18
  37. data/doc/error_reasons.rdoc +0 -77
  38. data/doc/guides/admin_activation.rdoc +0 -46
  39. data/doc/guides/already_authenticated.rdoc +0 -10
  40. data/doc/guides/alternative_login.rdoc +0 -46
  41. data/doc/guides/change_table_and_column_names.rdoc +0 -19
  42. data/doc/guides/create_account_programmatically.rdoc +0 -38
  43. data/doc/guides/delay_password.rdoc +0 -25
  44. data/doc/guides/email_only.rdoc +0 -16
  45. data/doc/guides/i18n.rdoc +0 -29
  46. data/doc/guides/internals.rdoc +0 -233
  47. data/doc/guides/links.rdoc +0 -12
  48. data/doc/guides/login_return.rdoc +0 -37
  49. data/doc/guides/migrate_password_hash_algorithm.rdoc +0 -15
  50. data/doc/guides/password_column.rdoc +0 -25
  51. data/doc/guides/password_confirmation.rdoc +0 -37
  52. data/doc/guides/password_requirements.rdoc +0 -43
  53. data/doc/guides/paths.rdoc +0 -51
  54. data/doc/guides/query_params.rdoc +0 -9
  55. data/doc/guides/redirects.rdoc +0 -17
  56. data/doc/guides/registration_field.rdoc +0 -68
  57. data/doc/guides/render_confirmation.rdoc +0 -17
  58. data/doc/guides/require_mfa.rdoc +0 -30
  59. data/doc/guides/reset_password_autologin.rdoc +0 -21
  60. data/doc/guides/share_configuration.rdoc +0 -34
  61. data/doc/guides/status_column.rdoc +0 -28
  62. data/doc/guides/totp_or_recovery.rdoc +0 -16
  63. data/doc/http_basic_auth.rdoc +0 -18
  64. data/doc/internal_request.rdoc +0 -539
  65. data/doc/json.rdoc +0 -56
  66. data/doc/jwt.rdoc +0 -52
  67. data/doc/jwt_cors.rdoc +0 -22
  68. data/doc/jwt_refresh.rdoc +0 -58
  69. data/doc/lockout.rdoc +0 -73
  70. data/doc/login.rdoc +0 -39
  71. data/doc/login_password_requirements_base.rdoc +0 -44
  72. data/doc/logout.rdoc +0 -22
  73. data/doc/otp.rdoc +0 -93
  74. data/doc/otp_lockout_email.rdoc +0 -30
  75. data/doc/otp_modify_email.rdoc +0 -19
  76. data/doc/otp_unlock.rdoc +0 -58
  77. data/doc/password_complexity.rdoc +0 -34
  78. data/doc/password_expiration.rdoc +0 -38
  79. data/doc/password_grace_period.rdoc +0 -24
  80. data/doc/password_pepper.rdoc +0 -52
  81. data/doc/path_class_methods.rdoc +0 -10
  82. data/doc/recovery_codes.rdoc +0 -61
  83. data/doc/release_notes/1.0.0.txt +0 -443
  84. data/doc/release_notes/1.1.0.txt +0 -8
  85. data/doc/release_notes/1.10.0.txt +0 -80
  86. data/doc/release_notes/1.11.0.txt +0 -32
  87. data/doc/release_notes/1.12.0.txt +0 -61
  88. data/doc/release_notes/1.13.0.txt +0 -34
  89. data/doc/release_notes/1.14.0.txt +0 -19
  90. data/doc/release_notes/1.15.0.txt +0 -21
  91. data/doc/release_notes/1.16.0.txt +0 -31
  92. data/doc/release_notes/1.17.0.txt +0 -23
  93. data/doc/release_notes/1.18.0.txt +0 -26
  94. data/doc/release_notes/1.19.0.txt +0 -116
  95. data/doc/release_notes/1.2.0.txt +0 -18
  96. data/doc/release_notes/1.20.0.txt +0 -175
  97. data/doc/release_notes/1.21.0.txt +0 -12
  98. data/doc/release_notes/1.22.0.txt +0 -11
  99. data/doc/release_notes/1.23.0.txt +0 -32
  100. data/doc/release_notes/1.3.0.txt +0 -21
  101. data/doc/release_notes/1.4.0.txt +0 -11
  102. data/doc/release_notes/1.5.0.txt +0 -74
  103. data/doc/release_notes/1.6.0.txt +0 -37
  104. data/doc/release_notes/1.7.0.txt +0 -6
  105. data/doc/release_notes/1.8.0.txt +0 -14
  106. data/doc/release_notes/1.9.0.txt +0 -15
  107. data/doc/release_notes/2.0.0.txt +0 -361
  108. data/doc/release_notes/2.1.0.txt +0 -31
  109. data/doc/release_notes/2.10.0.txt +0 -47
  110. data/doc/release_notes/2.11.0.txt +0 -31
  111. data/doc/release_notes/2.12.0.txt +0 -17
  112. data/doc/release_notes/2.13.0.txt +0 -19
  113. data/doc/release_notes/2.14.0.txt +0 -17
  114. data/doc/release_notes/2.15.0.txt +0 -48
  115. data/doc/release_notes/2.16.0.txt +0 -20
  116. data/doc/release_notes/2.17.0.txt +0 -10
  117. data/doc/release_notes/2.18.0.txt +0 -27
  118. data/doc/release_notes/2.19.0.txt +0 -61
  119. data/doc/release_notes/2.2.0.txt +0 -39
  120. data/doc/release_notes/2.20.0.txt +0 -10
  121. data/doc/release_notes/2.21.0.txt +0 -28
  122. data/doc/release_notes/2.22.0.txt +0 -43
  123. data/doc/release_notes/2.23.0.txt +0 -15
  124. data/doc/release_notes/2.24.0.txt +0 -15
  125. data/doc/release_notes/2.25.0.txt +0 -8
  126. data/doc/release_notes/2.26.0.txt +0 -45
  127. data/doc/release_notes/2.27.0.txt +0 -35
  128. data/doc/release_notes/2.28.0.txt +0 -16
  129. data/doc/release_notes/2.29.0.txt +0 -27
  130. data/doc/release_notes/2.3.0.txt +0 -37
  131. data/doc/release_notes/2.30.0.txt +0 -15
  132. data/doc/release_notes/2.31.0.txt +0 -47
  133. data/doc/release_notes/2.32.0.txt +0 -65
  134. data/doc/release_notes/2.33.0.txt +0 -18
  135. data/doc/release_notes/2.34.0.txt +0 -36
  136. data/doc/release_notes/2.35.0.txt +0 -22
  137. data/doc/release_notes/2.36.0.txt +0 -35
  138. data/doc/release_notes/2.4.0.txt +0 -22
  139. data/doc/release_notes/2.5.0.txt +0 -20
  140. data/doc/release_notes/2.6.0.txt +0 -37
  141. data/doc/release_notes/2.7.0.txt +0 -33
  142. data/doc/release_notes/2.8.0.txt +0 -20
  143. data/doc/release_notes/2.9.0.txt +0 -21
  144. data/doc/remember.rdoc +0 -79
  145. data/doc/reset_password.rdoc +0 -66
  146. data/doc/reset_password_notify.rdoc +0 -17
  147. data/doc/session_expiration.rdoc +0 -28
  148. data/doc/single_session.rdoc +0 -37
  149. data/doc/sms_codes.rdoc +0 -138
  150. data/doc/two_factor_base.rdoc +0 -70
  151. data/doc/update_password_hash.rdoc +0 -7
  152. data/doc/verify_account.rdoc +0 -67
  153. data/doc/verify_account_grace_period.rdoc +0 -19
  154. data/doc/verify_login_change.rdoc +0 -59
  155. data/doc/webauthn.rdoc +0 -118
  156. data/doc/webauthn_autofill.rdoc +0 -19
  157. data/doc/webauthn_login.rdoc +0 -16
  158. data/doc/webauthn_modify_email.rdoc +0 -19
  159. data/doc/webauthn_verify_account.rdoc +0 -9
data/README.rdoc DELETED
@@ -1,1555 +0,0 @@
1
- = Rodauth
2
-
3
- Rodauth is Ruby's most advanced authentication framework, designed
4
- to work in any rack application. It's built using Roda and Sequel,
5
- but it can be used with other web frameworks, database libraries,
6
- and databases.
7
-
8
- When used with PostgreSQL, MySQL, and Microsoft SQL Server in the
9
- default configuration, it offers additional security for password
10
- hashes by protecting access via database functions.
11
-
12
- Rodauth supports multiple multifactor authentication methods,
13
- multiple passwordless authentication methods, and offers both an
14
- HTML and JSON API for all supported features.
15
-
16
- == Design Goals
17
-
18
- * Security: Ship in a maximum security by default configuration
19
- * Simplicity: Allow for easy configuration via a DSL
20
- * Flexibility: Allow for easy overriding of any part of the framework
21
-
22
- == Features
23
-
24
- * Login
25
- * Logout
26
- * Change Password
27
- * Change Login
28
- * Reset Password
29
- * Create Account
30
- * Close Account
31
- * Verify Account
32
- * Confirm Password
33
- * Remember (Autologin via token)
34
- * Lockout (Bruteforce protection)
35
- * Audit Logging
36
- * Email Authentication (Passwordless login via email link)
37
- * WebAuthn (Multifactor authentication via WebAuthn)
38
- * WebAuthn Login (Passwordless login via WebAuthn)
39
- * WebAuthn Verify Account (Passwordless WebAuthn Setup)
40
- * WebAuthn Autofill (Autofill WebAuthn credentials on login)
41
- * WebAuthn Modify Email (Email when WebAuthn authenticator aded or removed)
42
- * OTP (Multifactor authentication via TOTP)
43
- * OTP Modify Email (Email when TOTP authentication setup or disabled)
44
- * OTP Unlock (Unlock TOTP authentication after lockout)
45
- * OTP Lockout Email (Email when TOTP authentication locked out or unlocked)
46
- * Recovery Codes (Multifactor authentication via backup codes)
47
- * SMS Codes (Multifactor authentication via SMS)
48
- * Verify Login Change (Verify new login before changing login)
49
- * Verify Account Grace Period (Don't require verification before login)
50
- * Password Grace Period (Don't require password entry if recently entered)
51
- * Password Complexity (More sophisticated checks)
52
- * Password Pepper
53
- * Disallow Password Reuse
54
- * Disallow Common Passwords
55
- * Password Expiration
56
- * Account Expiration
57
- * Session Expiration
58
- * Active Sessions (Prevent session reuse after logout, allow logout of all sessions)
59
- * Single Session (Only one active session per account)
60
- * JSON (JSON API support for all other features)
61
- * JWT (JSON Web Token support for all other features)
62
- * JWT Refresh (Access & Refresh Token)
63
- * JWT CORS (Cross-Origin Resource Sharing)
64
- * Update Password Hash (when hash cost changes)
65
- * Argon2
66
- * HTTP Basic Auth
67
- * Change Password Notify
68
- * Reset Password Notify
69
- * Internal Request
70
- * Path Class Methods
71
-
72
- == Resources
73
-
74
- Website :: http://rodauth.jeremyevans.net
75
- Demo Site :: http://rodauth-demo.jeremyevans.net
76
- Source :: http://github.com/jeremyevans/rodauth
77
- Bugs :: http://github.com/jeremyevans/rodauth/issues
78
- Discussion Forum (GitHub Discussions) :: https://github.com/jeremyevans/rodauth/discussions
79
- Alternate Discussion Forum (Google Groups) :: https://groups.google.com/forum/#!forum/rodauth
80
-
81
- == Dependencies
82
-
83
- There are some dependencies that Rodauth uses depending on the
84
- features in use. These are development dependencies instead of
85
- runtime dependencies in the gem as it is possible to run without them:
86
-
87
- tilt :: Used by all features unless in JSON API only mode or using
88
- :render=>false plugin option.
89
- rack_csrf :: Used for CSRF support if the <tt>csrf: :rack_csrf</tt> plugin
90
- option is given (the default is to use Roda's route_csrf
91
- plugin, as that allows for more secure request-specific
92
- tokens).
93
- bcrypt :: Used by default for password hashing, can be skipped
94
- if password_match? is overridden for custom authentication.
95
- argon2 :: Used by the argon2 feature as alternative to bcrypt for
96
- password hashing.
97
- mail :: Used by default for mailing in the reset_password, verify_account,
98
- verify_login_change, change_password_notify, lockout, and
99
- email_auth features.
100
- rotp :: Used by the otp feature
101
- rqrcode :: Used by the otp feature
102
- jwt :: Used by the jwt feature
103
- webauthn :: Used by the webauthn feature
104
-
105
- You can use <tt>gem install --development rodauth</tt> to install
106
- the development dependencies in order to run tests.
107
-
108
- == Security
109
-
110
- === Password Hash Access Via Database Functions
111
-
112
- By default on PostgreSQL, MySQL, and Microsoft SQL Server, Rodauth
113
- uses database functions to access password hashes, with the user
114
- running the application unable to get direct access to password
115
- hashes. This reduces the risk of an attacker being able to access
116
- password hashes and use them to attack other sites.
117
-
118
- The rest of this section describes this feature in more detail, but
119
- note that Rodauth does not require this feature be used and works
120
- correctly without it. There may be cases where you cannot use
121
- this feature, such as when using a different database or when you
122
- do not have full control over the database you are using.
123
-
124
- Passwords are hashed using bcrypt by default, and the password hashes are
125
- kept in a separate table from the accounts table, with a foreign key
126
- referencing the accounts table. Two database functions are added,
127
- one to retrieve the salt for a password, and the other to check
128
- if a given password hash matches the password hash for the user.
129
-
130
- Two database accounts are used. The first is the account that the
131
- application uses, which is referred to as the +app+ account. The +app+
132
- account does not have access to read the password hashes. The other
133
- account handles password hashes and is referred to as the +ph+
134
- account. The +ph+ account sets up the database functions that can
135
- retrieve the salt for a given account's password, and check if a
136
- password hash matches for a given account. The +ph+ account
137
- sets these functions up so that the +app+ account can execute the
138
- functions using the +ph+ account's permissions. This allows the
139
- +app+ account to check passwords without having access to read
140
- password hashes.
141
-
142
- While the +app+ account is not be able to read password hashes, it
143
- is still be able to insert password hashes, update passwords hashes,
144
- and delete password hashes, so the additional security is not that
145
- painful.
146
-
147
- By disallowing the +app+ account access to the password hashes,
148
- it is much more difficult for an attacker to access the password
149
- hashes, even if they are able to exploit an SQL injection or remote
150
- code execution vulnerability in the application.
151
-
152
- The reason for extra security in regards to password hashes stems from
153
- the fact that people tend to choose poor passwords and reuse passwords,
154
- so a compromise of one database containing password hashes can result
155
- in account access on other sites, making password hash storage of
156
- critical importance even if the other data stored is not that important.
157
-
158
- If you are storing other sensitive information in your database, you
159
- should consider using a similar approach in other areas (or all areas)
160
- of your application.
161
-
162
- === Tokens
163
-
164
- Account verification, password resets, email auth, verify login change,
165
- remember, and lockout tokens all use a similar approach. They all
166
- provide a token, in the format "account-id_long-random-string". By
167
- including the id of the account in the token, an attacker can only
168
- attempt to bruteforce the token for a single account, instead of being
169
- able to bruteforce tokens for all accounts at once (which would be
170
- possible if the token was just a random string).
171
-
172
- Additionally, all comparisons of tokens use a timing-safe comparison
173
- function to reduce the risk of timing attacks.
174
-
175
- == HMAC
176
-
177
- By default, for backwards compatibility, Rodauth does not use HMACs,
178
- but you are strongly encouraged to use the +hmac_secret+ configuration
179
- method to set an HMAC secret. Setting an HMAC secret will enable HMACs
180
- for additional security, as described below.
181
-
182
- === email_base feature
183
-
184
- All features that send email use this feature. Setting +hmac_secret+
185
- will make the tokens sent via email use an HMAC, while the raw token
186
- stored in the database will not use an HMAC. This will make it so
187
- if the tokens in the database are leaked (e.g. via an SQL injection
188
- vulnerability), they will not be usable without also having access
189
- to the +hmac_secret+. Without an HMAC, the raw token is sent in the
190
- email, and if the tokens in the database are leaked, they will be
191
- usable.
192
-
193
- To allow for an graceful transition, you can set +allow_raw_email_token?+
194
- to true temporarily. This will allow the raw tokens in previous sent
195
- emails to still work. This should only be set temporarily as it
196
- removes the security that +hmac_secret+ adds. Most features that
197
- send email have tokens that expire by default in 1 day. The
198
- exception is the verify_account feature, which has tokens that do
199
- not expire. For the verify_account feature, if the user requested
200
- an email before +hmac_secret+ was set, after +allow_raw_email_token+
201
- is no longer set, they will need to request the verification email
202
- be resent, in which case they will receive an email with a token
203
- that uses an HMAC.
204
-
205
- === remember feature
206
-
207
- Similar to the email_base feature, this uses HMACs for remember
208
- tokens, while storing the raw tokens in the database. This makes
209
- it so if the raw tokens in the database are leaked, the remember
210
- tokens are not usable without knowledge of the +hmac_secret+.
211
-
212
- The +raw_remember_token_deadline+ configuration method can
213
- be set to allow a previously set raw remember token to be used
214
- if the deadline for the remember token is before the given time.
215
- This allows for graceful transition to using HMACs for remember tokens.
216
- By default, the deadline is 14 days after the token is created, so this
217
- should be set to 14 days after the time you enable the HMAC for the
218
- remember feature if you are using the defaults.
219
-
220
- === otp feature
221
-
222
- Setting +hmac_secret+ will provide HMACed OTP keys to users, and
223
- would store the raw OTP keys in the database. This will make so
224
- if the raw OTP keys in the database are leaked, they will not be
225
- usable for two factor authentication without knowledge of the +hmac_secret+.
226
-
227
- Unfortunately, there can be no simple graceful transition for existing users.
228
- When introducing +hmac_secret+ to a Rodauth installation that already uses
229
- the otp feature, you will have to either revoke and replace all OTP keys,
230
- set +otp_keys_use_hmac?+ to false and continue to use raw OTP keys, or override
231
- +otp_keys_use_hmac?+ to return false if the user was issued an OTP key before
232
- +hmac_secret+ was added to the configuration, and true otherwise.
233
- +otp_keys_use_hmac?+ defaults to true if +hmac_secret+ is set, and false
234
- otherwise.
235
-
236
- If +otp_keys_use_hmac?+ is true, Rodauth will also ensure during OTP setup
237
- that the OTP key was generated by the server. If +otp_keys_use_hmac?+ is false,
238
- any OTP key in a valid format will be accepted during setup.
239
-
240
- If +otp_keys_use_hmac?+ is true, the jwt and otp features are in use and you
241
- are setting up OTP via JSON requests, you need to first send a POST request
242
- to the OTP setup route. This will return an error with the +otp_secret+ and
243
- +otp_raw_secret+ parameters in the JSON. These parameters should be submitted
244
- in the POST request to setup OTP, along with a valid OTP auth code for the
245
- +otp_secret+.
246
-
247
- === webauthn feature
248
-
249
- Setting +hmac_secret+ is required to use the webauthn feature, as it is
250
- used for checking that the provided authentication challenges have not
251
- been modified.
252
-
253
- === active_sessions feature
254
-
255
- Setting +hmac_secret+ is required to use the active_sessions feature,
256
- as the database stores an HMAC of the active session ID.
257
-
258
- === single_session feature
259
-
260
- Setting +hmac_secret+ will ensure the single session secret set in the
261
- session will be an HMACed. This does not affect security, as the session
262
- itself should at the least by protected by an HMAC (if not encrypted).
263
- This is only done for consistency, so that the raw tokens in the database
264
- are distinct from the tokens provided to the users. To allow for a
265
- graceful transition, +allow_raw_single_session_key?+ can be set to true.
266
-
267
- == PostgreSQL Database Setup
268
-
269
- In order to get full advantages of Rodauth's security design on PostgreSQL,
270
- multiple database accounts are involved:
271
-
272
- 1. database superuser account (usually postgres)
273
- 2. +app+ account (same name as application)
274
- 3. +ph+ account (application name with +_password+ appended)
275
-
276
- The database superuser account is used to load extensions related to the
277
- database. The application should never be run using the database
278
- superuser account.
279
-
280
- === Create database accounts
281
-
282
- If you are currently running your application using the database superuser
283
- account, the first thing you need to do is to create the +app+ database
284
- account. It's often best to name this account the same as the
285
- database name.
286
-
287
- You should also create the +ph+ database account which will handle access
288
- to the password hashes.
289
-
290
- Example for PostgreSQL:
291
-
292
- createuser -U postgres ${DATABASE_NAME}
293
- createuser -U postgres ${DATABASE_NAME}_password
294
-
295
- Note that if the database superuser account owns all of the items in the
296
- database, you'll need to change the ownership to the database account you
297
- just created. See https://gist.github.com/jeremyevans/8483320
298
- for a way to do that.
299
-
300
- === Create database
301
-
302
- In general, the +app+ account is the owner of the database, since it will
303
- own most of the tables:
304
-
305
- createdb -U postgres -O ${DATABASE_NAME} ${DATABASE_NAME}
306
-
307
- Note that this is not the most secure way to develop applications. For
308
- maximum security, you would want to use a separate database account as
309
- the owner of the tables, have the +app+ account not be the
310
- owner of any tables, and specifically grant the +app+ account only the
311
- minimum access it needs to work correctly. Doing that is beyond the
312
- scope of Rodauth, though.
313
-
314
- === Load extensions
315
-
316
- If you want to use the login features for Rodauth, you need to load the
317
- citext extension if you want to support case insensitive logins.
318
-
319
- Example:
320
-
321
- psql -U postgres -c "CREATE EXTENSION citext" ${DATABASE_NAME}
322
-
323
- Note that on Heroku, this extension can be loaded using a standard database
324
- account. If you want logins to be case sensitive (generally considered a
325
- bad idea), you don't need to use the PostgreSQL citext extension. Just
326
- remember to modify the migration below to use +String+ instead of +citext+
327
- for the email in that case.
328
-
329
- === Grant schema rights (PostgreSQL 15+)
330
-
331
- PostgreSQL 15 changed default database security so that only the database
332
- owner has writable access to the public schema. Rodauth expects the
333
- +ph+ account to have writable access to the public schema when setting
334
- things up. Temporarily grant that access (it will be revoked after the
335
- migration has run)
336
-
337
- psql -U postgres -c "GRANT CREATE ON SCHEMA public TO ${DATABASE_NAME}_password" ${DATABASE_NAME}
338
-
339
- === Using non-default schema
340
-
341
- PostgreSQL sets up new tables in the public schema by default.
342
- If you would like to use separate schemas per user, you can do:
343
-
344
- psql -U postgres -c "DROP SCHEMA public;" ${DATABASE_NAME}
345
- psql -U postgres -c "CREATE SCHEMA AUTHORIZATION ${DATABASE_NAME};" ${DATABASE_NAME}
346
- psql -U postgres -c "CREATE SCHEMA AUTHORIZATION ${DATABASE_NAME}_password;" ${DATABASE_NAME}
347
- psql -U postgres -c "GRANT USAGE ON SCHEMA ${DATABASE_NAME} TO ${DATABASE_NAME}_password;" ${DATABASE_NAME}
348
- psql -U postgres -c "GRANT USAGE ON SCHEMA ${DATABASE_NAME}_password TO ${DATABASE_NAME};" ${DATABASE_NAME}
349
-
350
- You'll need to modify the code to load the extension to specify the schema:
351
-
352
- psql -U postgres -c "CREATE EXTENSION citext SCHEMA ${DATABASE_NAME}" ${DATABASE_NAME}
353
-
354
- When running the migration for the +ph+ user you'll need to modify a couple
355
- things for the schema changes:
356
-
357
- create_table(:account_password_hashes) do
358
- foreign_key :id, Sequel[:${DATABASE_NAME}][:accounts], primary_key: true, type: :Bignum
359
- String :password_hash, null: false
360
- end
361
- Rodauth.create_database_authentication_functions(self, table_name: Sequel[:${DATABASE_NAME}_password][:account_password_hashes])
362
-
363
- # if using the disallow_password_reuse feature:
364
- create_table(:account_previous_password_hashes) do
365
- primary_key :id, type: :Bignum
366
- foreign_key :account_id, Sequel[:${DATABASE_NAME}][:accounts], type: :Bignum
367
- String :password_hash, null: false
368
- end
369
- Rodauth.create_database_previous_password_check_functions(self, table_name: Sequel[:${DATABASE_NAME}_password][:account_previous_password_hashes])
370
-
371
- You'll also need to use the following Rodauth configuration methods so that the
372
- app account calls functions in a separate schema:
373
-
374
- function_name do |name|
375
- "${DATABASE_NAME}_password.#{name}"
376
- end
377
- password_hash_table Sequel[:${DATABASE_NAME}_password][:account_password_hashes]
378
-
379
- # if using the disallow_password_reuse feature:
380
- previous_password_hash_table Sequel[:${DATABASE_NAME}_password][:account_previous_password_hashes]
381
-
382
- == MySQL Database Setup
383
-
384
- MySQL does not have the concept of object owners, and MySQL's GRANT/REVOKE
385
- support is much more limited than PostgreSQL's. When using MySQL, it is
386
- recommended to GRANT the +ph+ account ALL privileges on the database,
387
- including the ability to GRANT permissions to the +app+ account:
388
-
389
- CREATE USER '${DATABASE_NAME}'@'localhost' IDENTIFIED BY '${PASSWORD}';
390
- CREATE USER '${DATABASE_NAME}_password'@'localhost' IDENTIFIED BY '${OTHER_PASSWORD}';
391
- GRANT ALL ON ${DATABASE_NAME}.* TO '${DATABASE_NAME}_password'@'localhost' WITH GRANT OPTION;
392
-
393
- You should run all migrations as the +ph+ account, and GRANT specific access
394
- to the +app+ account as needed.
395
-
396
- Adding the database functions on MySQL may require setting the
397
- <tt>log_bin_trust_function_creators=1</tt> setting in the MySQL configuration.
398
-
399
- == Microsoft SQL Server Database Setup
400
-
401
- Microsoft SQL Server has a concept of database owners, but similar to MySQL
402
- usage it's recommended to use the +ph+ account as the superuser for the
403
- database, and have it GRANT permissions to the +app+ account:
404
-
405
- CREATE LOGIN rodauth_test WITH PASSWORD = 'rodauth_test';
406
- CREATE LOGIN rodauth_test_password WITH PASSWORD = 'rodauth_test';
407
- CREATE DATABASE rodauth_test;
408
- USE rodauth_test;
409
- CREATE USER rodauth_test FOR LOGIN rodauth_test;
410
- GRANT CONNECT, EXECUTE TO rodauth_test;
411
- EXECUTE sp_changedbowner 'rodauth_test_password';
412
-
413
- You should run all migrations as the +ph+ account, and GRANT specific access
414
- to the +app+ account as needed.
415
-
416
- == Creating tables
417
-
418
- Because two different database accounts are used, two different migrations
419
- are required, one for each database account. Here are example migrations.
420
- You can modify them to add support for additional columns, or remove tables
421
- or columns related to features that you don't need.
422
-
423
- First migration. On PostgreSQL, this should be run with the +app+ account,
424
- on MySQL and Microsoft SQL Server this should be run with the +ph+ account.
425
-
426
- Note that these migrations require Sequel 4.35.0+.
427
-
428
- Sequel.migration do
429
- up do
430
- extension :date_arithmetic
431
-
432
- # Used by the account verification and close account features
433
- create_table(:account_statuses) do
434
- Integer :id, primary_key: true
435
- String :name, null: false, unique: true
436
- end
437
- from(:account_statuses).import([:id, :name], [[1, 'Unverified'], [2, 'Verified'], [3, 'Closed']])
438
-
439
- db = self
440
- create_table(:accounts) do
441
- primary_key :id, type: :Bignum
442
- foreign_key :status_id, :account_statuses, null: false, default: 1
443
- if db.database_type == :postgres
444
- citext :email, null: false
445
- constraint :valid_email, email: /^[^,;@ \r\n]+@[^,@; \r\n]+\.[^,@; \r\n]+$/
446
- else
447
- String :email, null: false
448
- end
449
- if db.supports_partial_indexes?
450
- index :email, unique: true, where: {status_id: [1, 2]}
451
- else
452
- index :email, unique: true
453
- end
454
- end
455
-
456
- deadline_opts = proc do |days|
457
- if database_type == :mysql
458
- {null: false}
459
- else
460
- {null: false, default: Sequel.date_add(Sequel::CURRENT_TIMESTAMP, days: days)}
461
- end
462
- end
463
-
464
- # Used by the audit logging feature
465
- json_type = case database_type
466
- when :postgres
467
- :jsonb
468
- when :sqlite, :mysql
469
- :json
470
- else
471
- String
472
- end
473
- create_table(:account_authentication_audit_logs) do
474
- primary_key :id, type: :Bignum
475
- foreign_key :account_id, :accounts, null: false, type: :Bignum
476
- DateTime :at, null: false, default: Sequel::CURRENT_TIMESTAMP
477
- String :message, null: false
478
- column :metadata, json_type
479
- index [:account_id, :at], name: :audit_account_at_idx
480
- index :at, name: :audit_at_idx
481
- end
482
-
483
- # Used by the password reset feature
484
- create_table(:account_password_reset_keys) do
485
- foreign_key :id, :accounts, primary_key: true, type: :Bignum
486
- String :key, null: false
487
- DateTime :deadline, deadline_opts[1]
488
- DateTime :email_last_sent, null: false, default: Sequel::CURRENT_TIMESTAMP
489
- end
490
-
491
- # Used by the jwt refresh feature
492
- create_table(:account_jwt_refresh_keys) do
493
- primary_key :id, type: :Bignum
494
- foreign_key :account_id, :accounts, null: false, type: :Bignum
495
- String :key, null: false
496
- DateTime :deadline, deadline_opts[1]
497
- index :account_id, name: :account_jwt_rk_account_id_idx
498
- end
499
-
500
- # Used by the account verification feature
501
- create_table(:account_verification_keys) do
502
- foreign_key :id, :accounts, primary_key: true, type: :Bignum
503
- String :key, null: false
504
- DateTime :requested_at, null: false, default: Sequel::CURRENT_TIMESTAMP
505
- DateTime :email_last_sent, null: false, default: Sequel::CURRENT_TIMESTAMP
506
- end
507
-
508
- # Used by the verify login change feature
509
- create_table(:account_login_change_keys) do
510
- foreign_key :id, :accounts, primary_key: true, type: :Bignum
511
- String :key, null: false
512
- String :login, null: false
513
- DateTime :deadline, deadline_opts[1]
514
- end
515
-
516
- # Used by the remember me feature
517
- create_table(:account_remember_keys) do
518
- foreign_key :id, :accounts, primary_key: true, type: :Bignum
519
- String :key, null: false
520
- DateTime :deadline, deadline_opts[14]
521
- end
522
-
523
- # Used by the lockout feature
524
- create_table(:account_login_failures) do
525
- foreign_key :id, :accounts, primary_key: true, type: :Bignum
526
- Integer :number, null: false, default: 1
527
- end
528
- create_table(:account_lockouts) do
529
- foreign_key :id, :accounts, primary_key: true, type: :Bignum
530
- String :key, null: false
531
- DateTime :deadline, deadline_opts[1]
532
- DateTime :email_last_sent
533
- end
534
-
535
- # Used by the email auth feature
536
- create_table(:account_email_auth_keys) do
537
- foreign_key :id, :accounts, primary_key: true, type: :Bignum
538
- String :key, null: false
539
- DateTime :deadline, deadline_opts[1]
540
- DateTime :email_last_sent, null: false, default: Sequel::CURRENT_TIMESTAMP
541
- end
542
-
543
- # Used by the password expiration feature
544
- create_table(:account_password_change_times) do
545
- foreign_key :id, :accounts, primary_key: true, type: :Bignum
546
- DateTime :changed_at, null: false, default: Sequel::CURRENT_TIMESTAMP
547
- end
548
-
549
- # Used by the account expiration feature
550
- create_table(:account_activity_times) do
551
- foreign_key :id, :accounts, primary_key: true, type: :Bignum
552
- DateTime :last_activity_at, null: false
553
- DateTime :last_login_at, null: false
554
- DateTime :expired_at
555
- end
556
-
557
- # Used by the single session feature
558
- create_table(:account_session_keys) do
559
- foreign_key :id, :accounts, primary_key: true, type: :Bignum
560
- String :key, null: false
561
- end
562
-
563
- # Used by the active sessions feature
564
- create_table(:account_active_session_keys) do
565
- foreign_key :account_id, :accounts, type: :Bignum
566
- String :session_id
567
- Time :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
568
- Time :last_use, null: false, default: Sequel::CURRENT_TIMESTAMP
569
- primary_key [:account_id, :session_id]
570
- end
571
-
572
- # Used by the webauthn feature
573
- create_table(:account_webauthn_user_ids) do
574
- foreign_key :id, :accounts, primary_key: true, type: :Bignum
575
- String :webauthn_id, null: false
576
- end
577
- create_table(:account_webauthn_keys) do
578
- foreign_key :account_id, :accounts, type: :Bignum
579
- String :webauthn_id
580
- String :public_key, null: false
581
- Integer :sign_count, null: false
582
- Time :last_use, null: false, default: Sequel::CURRENT_TIMESTAMP
583
- primary_key [:account_id, :webauthn_id]
584
- end
585
-
586
- # Used by the otp feature
587
- create_table(:account_otp_keys) do
588
- foreign_key :id, :accounts, primary_key: true, type: :Bignum
589
- String :key, null: false
590
- Integer :num_failures, null: false, default: 0
591
- Time :last_use, null: false, default: Sequel::CURRENT_TIMESTAMP
592
- end
593
-
594
- # Used by the otp_unlock feature
595
- create_table(:account_otp_unlocks) do
596
- foreign_key :id, :accounts, primary_key: true, type: :Bignum
597
- Integer :num_successes, null: false, default: 1
598
- Time :next_auth_attempt_after, null: false, default: Sequel::CURRENT_TIMESTAMP
599
- end
600
-
601
- # Used by the recovery codes feature
602
- create_table(:account_recovery_codes) do
603
- foreign_key :id, :accounts, type: :Bignum
604
- String :code
605
- primary_key [:id, :code]
606
- end
607
-
608
- # Used by the sms codes feature
609
- create_table(:account_sms_codes) do
610
- foreign_key :id, :accounts, primary_key: true, type: :Bignum
611
- String :phone_number, null: false
612
- Integer :num_failures
613
- String :code
614
- DateTime :code_issued_at, null: false, default: Sequel::CURRENT_TIMESTAMP
615
- end
616
-
617
- case database_type
618
- when :postgres
619
- user = get(Sequel.lit('current_user')) + '_password'
620
- run "GRANT REFERENCES ON accounts TO #{user}"
621
- when :mysql, :mssql
622
- user = if database_type == :mysql
623
- get(Sequel.lit('current_user')).sub(/_password@/, '@')
624
- else
625
- get(Sequel.function(:DB_NAME))
626
- end
627
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_statuses TO #{user}"
628
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON accounts TO #{user}"
629
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_authentication_audit_logs TO #{user}"
630
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_password_reset_keys TO #{user}"
631
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_jwt_refresh_keys TO #{user}"
632
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_verification_keys TO #{user}"
633
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_login_change_keys TO #{user}"
634
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_remember_keys TO #{user}"
635
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_login_failures TO #{user}"
636
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_email_auth_keys TO #{user}"
637
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_lockouts TO #{user}"
638
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_password_change_times TO #{user}"
639
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_activity_times TO #{user}"
640
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_session_keys TO #{user}"
641
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_active_session_keys TO #{user}"
642
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_webauthn_user_ids TO #{user}"
643
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_webauthn_keys TO #{user}"
644
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_otp_keys TO #{user}"
645
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_otp_unlocks TO #{user}"
646
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_recovery_codes TO #{user}"
647
- run "GRANT SELECT, INSERT, UPDATE, DELETE ON account_sms_codes TO #{user}"
648
- end
649
- end
650
-
651
- down do
652
- drop_table(:account_sms_codes,
653
- :account_recovery_codes,
654
- :account_otp_unlocks,
655
- :account_otp_keys,
656
- :account_webauthn_keys,
657
- :account_webauthn_user_ids,
658
- :account_session_keys,
659
- :account_active_session_keys,
660
- :account_activity_times,
661
- :account_password_change_times,
662
- :account_email_auth_keys,
663
- :account_lockouts,
664
- :account_login_failures,
665
- :account_remember_keys,
666
- :account_login_change_keys,
667
- :account_verification_keys,
668
- :account_jwt_refresh_keys,
669
- :account_password_reset_keys,
670
- :account_authentication_audit_logs,
671
- :accounts,
672
- :account_statuses)
673
- end
674
- end
675
-
676
- Second migration, run using the +ph+ account:
677
-
678
- require 'rodauth/migrations'
679
-
680
- Sequel.migration do
681
- up do
682
- create_table(:account_password_hashes) do
683
- foreign_key :id, :accounts, primary_key: true, type: :Bignum
684
- String :password_hash, null: false
685
- end
686
- Rodauth.create_database_authentication_functions(self)
687
- case database_type
688
- when :postgres
689
- user = get(Sequel.lit('current_user')).sub(/_password\z/, '')
690
- run "REVOKE ALL ON account_password_hashes FROM public"
691
- run "REVOKE ALL ON FUNCTION rodauth_get_salt(int8) FROM public"
692
- run "REVOKE ALL ON FUNCTION rodauth_valid_password_hash(int8, text) FROM public"
693
- run "GRANT INSERT, UPDATE, DELETE ON account_password_hashes TO #{user}"
694
- run "GRANT SELECT(id) ON account_password_hashes TO #{user}"
695
- run "GRANT EXECUTE ON FUNCTION rodauth_get_salt(int8) TO #{user}"
696
- run "GRANT EXECUTE ON FUNCTION rodauth_valid_password_hash(int8, text) TO #{user}"
697
- when :mysql
698
- user = get(Sequel.lit('current_user')).sub(/_password@/, '@')
699
- db_name = get(Sequel.function(:database))
700
- run "GRANT EXECUTE ON #{db_name}.* TO #{user}"
701
- run "GRANT INSERT, UPDATE, DELETE ON account_password_hashes TO #{user}"
702
- run "GRANT SELECT (id) ON account_password_hashes TO #{user}"
703
- when :mssql
704
- user = get(Sequel.function(:DB_NAME))
705
- run "GRANT EXECUTE ON rodauth_get_salt TO #{user}"
706
- run "GRANT EXECUTE ON rodauth_valid_password_hash TO #{user}"
707
- run "GRANT INSERT, UPDATE, DELETE ON account_password_hashes TO #{user}"
708
- run "GRANT SELECT ON account_password_hashes(id) TO #{user}"
709
- end
710
-
711
- # Used by the disallow_password_reuse feature
712
- create_table(:account_previous_password_hashes) do
713
- primary_key :id, type: :Bignum
714
- foreign_key :account_id, :accounts, type: :Bignum
715
- String :password_hash, null: false
716
- end
717
- Rodauth.create_database_previous_password_check_functions(self)
718
-
719
- case database_type
720
- when :postgres
721
- user = get(Sequel.lit('current_user')).sub(/_password\z/, '')
722
- run "REVOKE ALL ON account_previous_password_hashes FROM public"
723
- run "REVOKE ALL ON FUNCTION rodauth_get_previous_salt(int8) FROM public"
724
- run "REVOKE ALL ON FUNCTION rodauth_previous_password_hash_match(int8, text) FROM public"
725
- run "GRANT INSERT, UPDATE, DELETE ON account_previous_password_hashes TO #{user}"
726
- run "GRANT SELECT(id, account_id) ON account_previous_password_hashes TO #{user}"
727
- run "GRANT USAGE ON account_previous_password_hashes_id_seq TO #{user}"
728
- run "GRANT EXECUTE ON FUNCTION rodauth_get_previous_salt(int8) TO #{user}"
729
- run "GRANT EXECUTE ON FUNCTION rodauth_previous_password_hash_match(int8, text) TO #{user}"
730
- when :mysql
731
- user = get(Sequel.lit('current_user')).sub(/_password@/, '@')
732
- db_name = get(Sequel.function(:database))
733
- run "GRANT EXECUTE ON #{db_name}.* TO #{user}"
734
- run "GRANT INSERT, UPDATE, DELETE ON account_previous_password_hashes TO #{user}"
735
- run "GRANT SELECT (id, account_id) ON account_previous_password_hashes TO #{user}"
736
- when :mssql
737
- user = get(Sequel.function(:DB_NAME))
738
- run "GRANT EXECUTE ON rodauth_get_previous_salt TO #{user}"
739
- run "GRANT EXECUTE ON rodauth_previous_password_hash_match TO #{user}"
740
- run "GRANT INSERT, UPDATE, DELETE ON account_previous_password_hashes TO #{user}"
741
- run "GRANT SELECT ON account_previous_password_hashes(id, account_id) TO #{user}"
742
- end
743
- end
744
-
745
- down do
746
- Rodauth.drop_database_previous_password_check_functions(self)
747
- Rodauth.drop_database_authentication_functions(self)
748
- drop_table(:account_previous_password_hashes, :account_password_hashes)
749
- end
750
- end
751
-
752
- To support multiple separate migration users, you can run the migration
753
- for the password user using Sequel's migration API:
754
-
755
- Sequel.extension :migration
756
- Sequel.postgres('DATABASE_NAME', user: 'PASSWORD_USER_NAME') do |db|
757
- Sequel::Migrator.run(db, 'path/to/password_user/migrations', table: 'schema_info_password')
758
- end
759
-
760
- If the database is not PostgreSQL, MySQL, or Microsoft SQL Server, or you
761
- cannot use multiple user accounts, just combine the two migrations into a
762
- single migration, removing all the code related to database permissions
763
- and database functions.
764
-
765
- One thing to notice in the above migrations is that Rodauth uses additional
766
- tables for additional features, instead of additional columns in a single
767
- table.
768
-
769
- === Revoking schema rights (PostgreSQL 15+)
770
-
771
- If you explicit granted access to the public schema before running the
772
- migration, revoke it afterward:
773
-
774
- psql -U postgres -c "REVOKE CREATE ON SCHEMA public FROM ${DATABASE_NAME}_password" ${DATABASE_NAME}
775
-
776
- === Locking Down (PostgreSQL only)
777
-
778
- After running the migrations, you can increase security slightly by making
779
- it not possible for the +ph+ account to login to the database directly.
780
- This can be accomplished by modifying the +pg_hba.conf+ file. You can also
781
- consider restricting access using GRANT/REVOKE.
782
-
783
- You can restrict access to the database itself to just the +app+ account. You
784
- can run this using the +app+ account, since that account owns the database:
785
-
786
- GRANT ALL ON DATABASE ${DATABASE_NAME} TO ${DATABASE_NAME};
787
- REVOKE ALL ON DATABASE ${DATABASE_NAME} FROM public;
788
-
789
- You can also restrict access to the public schema (this is not needed if you
790
- are using a custom schema). Note that by default, the database superuser
791
- owns the public schema, so you have to run this as the database superuser
792
- account (generally +postgres+):
793
-
794
- GRANT ALL ON SCHEMA public TO ${DATABASE_NAME};
795
- GRANT USAGE ON SCHEMA public TO ${DATABASE_NAME}_password;
796
- REVOKE ALL ON SCHEMA public FROM public;
797
-
798
- If you are using MySQL or Microsoft SQL Server, please consult their
799
- documentation for how to restrict access so that the +ph+ account cannot
800
- login directly.
801
-
802
- == Usage
803
-
804
- === Basic Usage
805
-
806
- Rodauth is a Roda plugin and loaded the same way other Roda plugins
807
- are loaded:
808
-
809
- plugin :rodauth do
810
- end
811
-
812
- The block passed to the plugin call uses the Rodauth configuration DSL.
813
- The one configuration method that should always be used is +enable+,
814
- which chooses which features you would like to load:
815
-
816
- plugin :rodauth do
817
- enable :login, :logout
818
- end
819
-
820
- Once features are loaded, you can use any of the configuration methods
821
- supported by the features. There are two types of configuration
822
- methods. The first type are called auth methods, and they take a
823
- block which overrides the default method that Rodauth uses. Inside the
824
- block, you can call super if you want to get the default behavior, though
825
- you must provide explicit arguments to super. There is no need to
826
- call super in before or after hooks, though. For example, if you want to
827
- add additional logging when a user logs in:
828
-
829
- plugin :rodauth do
830
- enable :login, :logout
831
- after_login do
832
- LOGGER.info "#{account[:email]} logged in!"
833
- end
834
- end
835
-
836
- Inside the block, you are in the context of the Rodauth::Auth
837
- instance related to the request. This object has access to everything
838
- related to the request via methods:
839
-
840
- request :: RodaRequest instance
841
- response :: RodaResponse instance
842
- scope :: Roda instance
843
- session :: session hash
844
- flash :: flash message hash
845
- account :: account hash (if set by an earlier Rodauth method)
846
- current_route :: route name symbol (if Rodauth is handling the route)
847
-
848
- So if you want to log the IP address for the user during login:
849
-
850
- plugin :rodauth do
851
- enable :login, :logout
852
- after_login do
853
- LOGGER.info "#{account[:email]} logged in from #{request.ip}"
854
- end
855
- end
856
-
857
- The second type of configuration methods are called auth value
858
- methods. They are similar to auth methods, but instead of just
859
- accepting a block, they can optionally accept a single argument
860
- without a block, which will be treated as a block that just returns
861
- that value. For example, the accounts_table method sets the database
862
- table storing accounts, so to override it, you can call the method
863
- with a symbol for the table:
864
-
865
- plugin :rodauth do
866
- enable :login, :logout
867
- accounts_table :users
868
- end
869
-
870
- Note that all auth value methods can still take a block, allowing
871
- overriding for all behavior, using any information from the request:
872
-
873
- plugin :rodauth do
874
- enable :login, :logout
875
- accounts_table do
876
- request.ip.start_with?("192.168.1.") ? :admins : :users
877
- end
878
- end
879
-
880
- By allowing every configuration method to take a block, Rodauth
881
- should be flexible enough to integrate into most legacy systems.
882
-
883
- === Plugin Options
884
-
885
- When loading the rodauth plugin, you can also pass an options hash,
886
- which configures which dependent plugins should be loaded. Options:
887
-
888
- :csrf :: Set to +false+ to not load a csrf plugin. Set to +:rack_csrf+
889
- to use the csrf plugin instead of the route_csrf plugin.
890
- :flash :: Set to +false+ to not load the flash plugin
891
- :render :: Set to +false+ to not load the render plugin. This is useful
892
- to avoid the dependency on tilt when using alternative view libaries.
893
- :json :: Set to +true+ to load the json and json_parser plugins. Set
894
- to +:only+ to only load those plugins and not any other plugins.
895
- Note that if you are enabling features that send email, you
896
- still need to load the render plugin manually.
897
- :name :: Provide a name for the given Rodauth configuration, used to
898
- support multiple Rodauth configurations in a given Roda application.
899
- :auth_class :: Provide a specific Rodauth::Auth subclass that should be set
900
- on the Roda application. By default, an anonymous
901
- Rodauth::Auth subclass is created.
902
-
903
- === Feature Documentation
904
-
905
- The options/methods for the supported features are listed on a
906
- separate page per feature. If these links are not active, please
907
- view the appropriate file in the doc directory.
908
-
909
- * {Base}[rdoc-ref:doc/base.rdoc] (this feature is autoloaded)
910
- * {Login Password Requirements Base}[rdoc-ref:doc/login_password_requirements_base.rdoc] (this feature is autoloaded by features that set logins/passwords)
911
- * {Email Base}[rdoc-ref:doc/email_base.rdoc] (this feature is autoloaded by features that send email)
912
- * {Two Factor Base}[rdoc-ref:doc/two_factor_base.rdoc] (this feature is autoloaded by 2 factor authentication features)
913
- * {Account Expiration}[rdoc-ref:doc/account_expiration.rdoc]
914
- * {Active Sessions}[rdoc-ref:doc/active_sessions.rdoc]
915
- * {Audit Logging}[rdoc-ref:doc/audit_logging.rdoc]
916
- * {Argon2}[rdoc-ref:doc/argon2.rdoc]
917
- * {Change Login}[rdoc-ref:doc/change_login.rdoc]
918
- * {Change Password}[rdoc-ref:doc/change_password.rdoc]
919
- * {Change Password Notify}[rdoc-ref:doc/change_password_notify.rdoc]
920
- * {Close Account}[rdoc-ref:doc/close_account.rdoc]
921
- * {Confirm Password}[rdoc-ref:doc/confirm_password.rdoc]
922
- * {Create Account}[rdoc-ref:doc/create_account.rdoc]
923
- * {Disallow Common Passwords}[rdoc-ref:doc/disallow_common_passwords.rdoc]
924
- * {Disallow Password Reuse}[rdoc-ref:doc/disallow_password_reuse.rdoc]
925
- * {Email Authentication}[rdoc-ref:doc/email_auth.rdoc]
926
- * {HTTP Basic Auth}[rdoc-ref:doc/http_basic_auth.rdoc]
927
- * {Internal Request}[rdoc-ref:doc/internal_request.rdoc]
928
- * {JSON}[rdoc-ref:doc/json.rdoc]
929
- * {JWT CORS}[rdoc-ref:doc/jwt_cors.rdoc]
930
- * {JWT Refresh}[rdoc-ref:doc/jwt_refresh.rdoc]
931
- * {JWT}[rdoc-ref:doc/jwt.rdoc]
932
- * {Lockout}[rdoc-ref:doc/lockout.rdoc]
933
- * {Login}[rdoc-ref:doc/login.rdoc]
934
- * {Logout}[rdoc-ref:doc/logout.rdoc]
935
- * {OTP}[rdoc-ref:doc/otp.rdoc]
936
- * {OTP Lockout Email}[rdoc-ref:doc/otp_lockout_email.rdoc]
937
- * {OTP Modify Email}[rdoc-ref:doc/otp_modify_email.rdoc]
938
- * {OTP Unlock}[rdoc-ref:doc/otp_unlock.rdoc]
939
- * {Password Complexity}[rdoc-ref:doc/password_complexity.rdoc]
940
- * {Password Expiration}[rdoc-ref:doc/password_expiration.rdoc]
941
- * {Password Grace Period}[rdoc-ref:doc/password_grace_period.rdoc]
942
- * {Password Pepper}[rdoc-ref:doc/password_pepper.rdoc]
943
- * {Path Class Methods}[rdoc-ref:doc/path_class_methods.rdoc]
944
- * {Recovery Codes}[rdoc-ref:doc/recovery_codes.rdoc]
945
- * {Remember}[rdoc-ref:doc/remember.rdoc]
946
- * {Reset Password}[rdoc-ref:doc/reset_password.rdoc]
947
- * {Reset Password Notify}[rdoc-ref:doc/reset_password_notify.rdoc]
948
- * {Session Expiration}[rdoc-ref:doc/session_expiration.rdoc]
949
- * {Single Session}[rdoc-ref:doc/single_session.rdoc]
950
- * {SMS Codes}[rdoc-ref:doc/sms_codes.rdoc]
951
- * {Update Password Hash}[rdoc-ref:doc/update_password_hash.rdoc]
952
- * {Verify Account}[rdoc-ref:doc/verify_account.rdoc]
953
- * {Verify Account Grace Period}[rdoc-ref:doc/verify_account_grace_period.rdoc]
954
- * {Verify Login Change}[rdoc-ref:doc/verify_login_change.rdoc]
955
- * {WebAuthn}[rdoc-ref:doc/webauthn.rdoc]
956
- * {WebAuthn Autofill}[rdoc-ref:doc/webauthn_autofill.rdoc]
957
- * {WebAuthn Login}[rdoc-ref:doc/webauthn_login.rdoc]
958
- * {WebAuthn Modify Email}[rdoc-ref:doc/webauthn_modify_email.rdoc]
959
- * {WebAuthn Verify Account}[rdoc-ref:doc/webauthn_verify_account.rdoc]
960
-
961
- === Calling Rodauth in the Routing Tree
962
-
963
- In general, you will usually want to call +r.rodauth+ early in your
964
- route block:
965
-
966
- route do |r|
967
- r.rodauth
968
-
969
- # ...
970
- end
971
-
972
- Note that will allow Rodauth to run, but it won't force people
973
- to login or add any security to your site. If you want to force
974
- all users to login, you need to redirect to them login page if
975
- they are not already logged in:
976
-
977
- route do |r|
978
- r.rodauth
979
- rodauth.require_authentication
980
-
981
- # ...
982
- end
983
-
984
- If only certain parts of your site require logins, then you can
985
- only redirect if they are not logged in certain branches of the
986
- routing tree:
987
-
988
- route do |r|
989
- r.rodauth
990
-
991
- r.on "admin" do
992
- rodauth.require_authentication
993
-
994
- # ...
995
- end
996
-
997
- # ...
998
- end
999
-
1000
- In some cases you may want to have rodauth run inside a branch of
1001
- the routing tree, instead of in the root. You can do this by
1002
- setting a +:prefix+ when configuring Rodauth, and calling +r.rodauth+
1003
- inside a matching routing tree branch:
1004
-
1005
- plugin :rodauth do
1006
- enable :login, :logout
1007
- prefix "/auth"
1008
- end
1009
-
1010
- route do |r|
1011
- r.on "auth" do
1012
- r.rodauth
1013
- end
1014
-
1015
- rodauth.require_authentication
1016
-
1017
- # ...
1018
- end
1019
-
1020
- === +rodauth+ Methods
1021
-
1022
- Most of Rodauth's functionality is exposed via +r.rodauth+, which allows
1023
- Rodauth to handle routes for the features you have enabled (such as +/login+
1024
- for login). However, as you have seen above, you may want to call methods on
1025
- the +rodauth+ object, such as for checking if the current request has been
1026
- authenticated.
1027
-
1028
- Here are methods designed to be callable on the +rodauth+ object outside
1029
- +r.rodauth+:
1030
-
1031
- require_login :: Require the session be logged in, redirecting the request to the
1032
- login page if the request has not been logged in.
1033
- require_authentication :: Similar to +require_login+, but also requires
1034
- two factor authentication if the account has setup
1035
- two factor authentication. Redirects the request to
1036
- the two factor authentication page if logged in but not
1037
- authenticated via two factors.
1038
- require_account :: Similar to +require_authentication+, but also loads the logged
1039
- in account to ensure it exists in the database. If the account
1040
- doesn't exist, or if it exists but isn't verified, the session
1041
- is cleared and the request redirected to the login page.
1042
- logged_in? :: Whether the session has been logged in.
1043
- authenticated? :: Similar to +logged_in?+, but if the account has setup two
1044
- factor authentication, whether the session has authenticated
1045
- via two factors.
1046
- account! :: Returns the current account record if it has already been loaded,
1047
- otherwise retrieves the account from session if logged in.
1048
- authenticated_by :: An array of strings for successful authentication methods for
1049
- the current session (e.g. password/remember/webauthn).
1050
- possible_authentication_methods :: An array of strings for possible authentication
1051
- types that can be used for the account.
1052
- autologin_type :: If the current session was authenticated via autologin, the
1053
- type of autologin used.
1054
- require_two_factor_setup :: (two_factor_base feature) Require the session to have
1055
- setup two factor authentication, redirecting the
1056
- request to the two factor authentication setup page
1057
- if not.
1058
- uses_two_factor_authentication? :: (two_factor_base feature) Whether the account
1059
- for the current session has setup two factor
1060
- authentication.
1061
- update_last_activity :: (account_expiration feature) Update the last activity
1062
- time for the current account. Only makes sense to use
1063
- this if you are expiring accounts based on last activity.
1064
- require_current_password :: (password_expiration feature) Require a current
1065
- password, redirecting the request to the change
1066
- password page if the password for the account has
1067
- expired.
1068
- require_password_authentication :: (confirm_password feature) If not authenticated
1069
- via password and the account has a password,
1070
- redirect to the password confirmation page,
1071
- saving the current location to redirect back
1072
- to after password has been successfully
1073
- confirmed. If the password_grace_period feature
1074
- is used, also redirect if the password has not
1075
- been recently entered.
1076
- load_memory :: (remember feature) If the session has not been authenticated, look
1077
- for the remember cookie. If present and valid, automatically
1078
- log the session in, but mark that it was logged in via a remember
1079
- key.
1080
- logged_in_via_remember_key? :: (remember feature) Whether the current session has
1081
- been logged in via a remember key. For security
1082
- sensitive actions where you want to require the user
1083
- to reenter the password, you can use the
1084
- confirm_password feature.
1085
- http_basic_auth :: (http_basic_auth feature) Use HTTP Basic Authentication information
1086
- to login the user if provided.
1087
- require_http_basic_auth :: (http_basic_auth feature) Require that HTTP Basic
1088
- Authentication be provided in the request.
1089
- check_session_expiration :: (session_expiration feature) Check whether the current
1090
- session has expired, automatically logging the session
1091
- out if so.
1092
- check_active_session :: (active_sessions feature) Check whether the current session
1093
- is still active, automatically logging the session out if not.
1094
- check_single_session :: (single_session feature) Check whether the current
1095
- session is still the only valid session, automatically logging
1096
- the session out if not.
1097
- verified_account? :: (verify_grace_period feature) Whether the account is currently
1098
- verified. If false, it is because the account is allowed to
1099
- login as they are in the grace period.
1100
- locked_out? :: (lockout feature) Whether the account for the current session has been
1101
- locked out.
1102
- authenticated_webauthn_id :: (webauthn feature) If the current session was
1103
- authenticated via webauthn, the webauthn id of the
1104
- credential used.
1105
- *_path :: One of these is added for each of the routes added by Rodauth, giving the
1106
- relative path to the route. Any options passed to this method will be
1107
- converted into query parameters.
1108
- *_url :: One of these is added for each of the routes added by Rodauth, giving the
1109
- URL to the route. Any options passed to this method will be converted
1110
- into query parameters.
1111
-
1112
- === Calling Rodauth Methods for Other Accounts
1113
-
1114
- In some cases, you may want to interact with Rodauth directly on behalf
1115
- of a user. For example, let's say you want to create accounts or change passwords
1116
- for existing accounts. Using Rodauth's internal_request feature, you can do this
1117
- by:
1118
-
1119
- plugin :rodauth do
1120
- enable :create_account, :change_password, :internal_request
1121
- end
1122
- rodauth.create_account(login: 'foo@example.com', password: '...')
1123
- rodauth.change_password(account_id: 24601, password: '...')
1124
-
1125
- Here the +rodauth+ method is called as the Roda class level, which returns
1126
- the appropriate <tt>Rodauth::Auth</tt> subclass. You call internal request
1127
- methods on that class to perform actions on behalf of a user. See the
1128
- {internal request feature documentation}[rdoc-ref:doc/internal_request.rdoc]
1129
- for details.
1130
-
1131
- == Using Rodauth as a Library
1132
-
1133
- Rodauth was designed to serve as an authentication framework for Rack applications.
1134
- However, Rodauth can be used purely as a library outside of a web application. You
1135
- can do this by requiring +rodauth+, and using the +Rodauth.lib+ method to return
1136
- a <tt>Rodauth::Auth</tt> subclass, which you can call methods on. You pass the
1137
- +Rodauth.lib+ method an optional hash of Rodauth plugin options and a Rodauth
1138
- configuration block:
1139
-
1140
- require 'rodauth'
1141
- rodauth = Rodauth.lib do
1142
- enable :create_account, :change_password
1143
- end
1144
- rodauth.create_account(login: 'foo@example.com', password: '...')
1145
- rodauth.change_password(account_id: 24601, password: '...')
1146
-
1147
- This supports builds on top of the internal_request support (it implicitly loads
1148
- the internal_request feature before processing the configuration block), and
1149
- allows the use of Rodauth in non-web applications. Note that you still have to
1150
- setup a Sequel::Database connection for Rodauth to use for data storage.
1151
-
1152
- === With Multiple Configurations
1153
-
1154
- Rodauth supports using multiple rodauth configurations in the same
1155
- application. You just need to load the plugin a second time,
1156
- providing a name for any alternate configuration:
1157
-
1158
- plugin :rodauth do
1159
- end
1160
- plugin :rodauth, name: :secondary do
1161
- end
1162
-
1163
- Then in your routing code, any time you call rodauth, you can provide
1164
- the name as an argument to use that configuration:
1165
-
1166
- route do |r|
1167
- r.on 'secondary' do
1168
- r.rodauth(:secondary)
1169
- end
1170
-
1171
- r.rodauth
1172
- end
1173
-
1174
- By default, alternate configurations will use the same session keys as the
1175
- primary configuration, which may be undesirable. To ensure session state is
1176
- separated between configurations, you can set a session key prefix for
1177
- alternate configurations. If you are using the remember feature in both
1178
- configurations, you may also want to set a different remember key in the
1179
- alternate configuration:
1180
-
1181
- plugin :rodauth, name: :secondary do
1182
- session_key_prefix "secondary_"
1183
- remember_cookie_key "_secondary_remember"
1184
- end
1185
-
1186
- === With Password Hashes Inside the Accounts Table
1187
-
1188
- You can use Rodauth if you are storing password hashes in the same
1189
- table as the accounts. You just need to specify which column
1190
- stores the password hash:
1191
-
1192
- plugin :rodauth do
1193
- account_password_hash_column :password_hash
1194
- end
1195
-
1196
- When this option is set, Rodauth will do the password hash check
1197
- in ruby.
1198
-
1199
- === When Using PostgreSQL/MySQL/Microsoft SQL Server without Database Functions
1200
-
1201
- If you want to use Rodauth on PostgreSQL, MySQL, or Microsoft SQL Server
1202
- without using database functions for authentication, but still storing password
1203
- hashes in a separate table, you can do so:
1204
-
1205
- plugin :rodauth do
1206
- use_database_authentication_functions? false
1207
- end
1208
-
1209
- Conversely, if you implement the rodauth_get_salt and
1210
- rodauth_valid_password_hash functions on a database that isn't
1211
- PostgreSQL, MySQL, or Microsoft SQL Server, you can set this value to true.
1212
-
1213
- === With Custom Authentication
1214
-
1215
- You can use Rodauth with other authentication types, by using some
1216
- of Rodauth's configuration methods.
1217
-
1218
- Note that when using custom authentication, using some of Rodauth's
1219
- features such as change login and change password either would not
1220
- make sense or would require some additional custom configuration.
1221
- The login and logout features should work correctly with the examples
1222
- below, though.
1223
-
1224
- ==== Using LDAP Authentication
1225
-
1226
- If you have accounts stored in the database, but authentication happens
1227
- via LDAP, you can use the +simple_ldap_authenticator+ library:
1228
-
1229
- require 'simple_ldap_authenticator'
1230
- plugin :rodauth do
1231
- enable :login, :logout
1232
- require_bcrypt? false
1233
- password_match? do |password|
1234
- SimpleLdapAuthenticator.valid?(account[:email], password)
1235
- end
1236
- end
1237
-
1238
- If you aren't storing accounts in the database, but want to allow
1239
- any valid LDAP user to login, you can do something like this:
1240
-
1241
- require 'simple_ldap_authenticator'
1242
- plugin :rodauth do
1243
- enable :login, :logout
1244
-
1245
- # Don't require the bcrypt library, since using LDAP for auth
1246
- require_bcrypt? false
1247
-
1248
- # Store session value in :login key, since the :account_id
1249
- # default wouldn't make sense
1250
- session_key :login
1251
-
1252
- # Use the login provided as the session value
1253
- account_session_value{account}
1254
-
1255
- # Treat the login itself as the account
1256
- account_from_login{|l| l.to_s}
1257
-
1258
- password_match? do |password|
1259
- SimpleLdapAuthenticator.valid?(account, password)
1260
- end
1261
- end
1262
-
1263
- ==== Using Facebook Authentication
1264
-
1265
- Here's an example of authentication using Facebook with a JSON API.
1266
- This setup assumes you have client-side code to submit JSON POST requests
1267
- to +/login+ with an +access_token+ parameter that is set to the user's
1268
- Facebook OAuth access token.
1269
-
1270
-
1271
- require 'koala'
1272
- plugin :rodauth do
1273
- enable :login, :logout, :jwt
1274
-
1275
- require_bcrypt? false
1276
- session_key :facebook_email
1277
- account_session_value{account}
1278
-
1279
- login_param 'access_token'
1280
-
1281
- account_from_login do |access_token|
1282
- fb = Koala::Facebook::API.new(access_token)
1283
- if me = fb.get_object('me', fields: [:email])
1284
- me['email']
1285
- end
1286
- end
1287
-
1288
- # there is no password!
1289
- password_match? do |pass|
1290
- true
1291
- end
1292
- end
1293
-
1294
- === With Rails
1295
-
1296
- If you're using Rails, you can use the
1297
- {rodauth-rails}[https://github.com/janko/rodauth-rails] gem which provides
1298
- Rails integration for Rodauth. Some of its features include:
1299
-
1300
- * generators for Rodauth & Sequel configuration, as well as views and mailers
1301
- * uses Rails' flash messages and CSRF protection
1302
- * automatically sets HMAC secret to Rails' secret key base
1303
- * uses Action Controller & Action View for rendering templates
1304
- * uses Action Mailer for sending emails
1305
-
1306
- Follow the instructions in the rodauth-rails README to get started.
1307
-
1308
- === With Other Web Frameworks
1309
-
1310
- You can use Rodauth even if your application does not use the Roda web
1311
- framework. This is possible by adding a Roda middleware that uses
1312
- Rodauth:
1313
-
1314
- require 'roda'
1315
-
1316
- class RodauthApp < Roda
1317
- plugin :middleware
1318
- plugin :rodauth do
1319
- enable :login
1320
- end
1321
-
1322
- route do |r|
1323
- r.rodauth
1324
- rodauth.require_authentication
1325
- env['rodauth'] = rodauth
1326
- end
1327
- end
1328
-
1329
- use RodauthApp
1330
-
1331
- Note that Rodauth expects the Roda app it is used in to provide a
1332
- layout. So if you are using Rodauth as middleware for another app,
1333
- if you don't have a +views/layout.erb+ file that Rodauth can use,
1334
- you should probably also add load Roda's +render+ plugin
1335
- with the appropriate settings that allow Rodauth to use the same
1336
- layout as the application.
1337
-
1338
- By setting <tt>env['rodauth'] = rodauth</tt> in the route block
1339
- inside the middleware, you can easily provide a way for your
1340
- application to call Rodauth methods.
1341
-
1342
- If you're using the remember feature with +extend_remember_deadline?+ set to
1343
- true, you'll want to load roda's middleware plugin with
1344
- <tt>forward_response_headers: true</tt> option, so that +Set-Cookie+ header changes
1345
- from the +load_memory+ call in the route block are propagated when the request
1346
- is forwarded to the main app.
1347
-
1348
- Here are some examples of integrating Rodauth into applications that
1349
- don't use Roda:
1350
-
1351
- * {Ginatra, a Sinatra-based git repository viewer}[https://github.com/jeremyevans/ginatra/commit/28108ebec96e8d42596ee55b01c3f7b50c155dd1]
1352
- * {Rodauth's demo site as a Rails 6 application}[https://github.com/janko/rodauth-demo-rails]
1353
- * {Grape application}[https://github.com/davydovanton/grape-rodauth]
1354
- * {Hanami application}[https://github.com/davydovanton/rodauth_hanami]
1355
-
1356
- === Using 2 Factor Authentication
1357
-
1358
- Rodauth ships with 2 factor authentication support via the following
1359
- methods:
1360
-
1361
- * WebAuthn
1362
- * TOTP (Time-Based One-Time Passwords, RFC 6238).
1363
- * SMS Codes
1364
- * Recovery Codes
1365
-
1366
- There are multiple ways to integrate 2 factor authentication with
1367
- Rodauth, based on the needs of the application. By default, SMS
1368
- codes and recovery codes are treated only as backup 2nd factors,
1369
- a user cannot enable them without first enabling another 2nd factor
1370
- authentication method. However, you can change this by using
1371
- a configuration method.
1372
-
1373
- If you want to support but not require 2 factor authentication:
1374
-
1375
- plugin :rodauth do
1376
- enable :login, :logout, :otp, :recovery_codes, :sms_codes
1377
- end
1378
- route do |r|
1379
- r.rodauth
1380
- rodauth.require_authentication
1381
-
1382
- # ...
1383
- end
1384
-
1385
- If you want to force all users to use 2 factor authentication, requiring users
1386
- that don't currently have two authentication to set it up:
1387
-
1388
- route do |r|
1389
- r.rodauth
1390
- rodauth.require_authentication
1391
- rodauth.require_two_factor_setup
1392
-
1393
- # ...
1394
- end
1395
-
1396
- Similarly to requiring authentication in general, it's possible to require
1397
- login authentication for most of the site, but require 2 factor
1398
- authentication only for particular branches:
1399
-
1400
- route do |r|
1401
- r.rodauth
1402
- rodauth.require_login
1403
-
1404
- r.on "admin" do
1405
- rodauth.require_two_factor_authenticated
1406
- end
1407
-
1408
- # ...
1409
- end
1410
-
1411
- === JSON API Support
1412
-
1413
- To add support for handling JSON responses, you can pass the +:json+
1414
- option to the plugin, and enable the JWT feature in addition to
1415
- other features you plan to use:
1416
-
1417
- plugin :rodauth, json: true do
1418
- enable :login, :logout, :jwt
1419
- end
1420
-
1421
- If you do not want to load the HTML plugins that Rodauth usually loads
1422
- (render, csrf, flash, h), because you are building a JSON-only API,
1423
- pass <tt>:json => :only</tt>
1424
-
1425
- plugin :rodauth, json: :only do
1426
- enable :login, :logout, :jwt
1427
- end
1428
-
1429
- Note that by default, the features that send email depend on the
1430
- render plugin, so if using the <tt>json: :only</tt> option, you
1431
- either need to load the render plugin manually or you need to
1432
- use the necessary *_email_body configuration options to specify
1433
- the body of the emails.
1434
-
1435
- The JWT feature enables JSON API support for all of the other features
1436
- that Rodauth ships with. If you would like JSON API access that still uses
1437
- rack session for storing session data, enable the JSON feature instead:
1438
-
1439
- plugin :rodauth, json: true do
1440
- enable :login, :logout, :json
1441
- only_json? true # if you want to only handle JSON requests
1442
- end
1443
-
1444
- === Adding Custom Methods to the +rodauth+ Object
1445
-
1446
- Inside the configuration block, you can use +auth_class_eval+ to add
1447
- custom methods that will be callable on the +rodauth+ object.
1448
-
1449
- plugin :rodauth do
1450
- enable :login
1451
-
1452
- auth_class_eval do
1453
- def require_admin
1454
- request.redirect("/") unless account[:admin]
1455
- end
1456
- end
1457
- end
1458
-
1459
- route do |r|
1460
- r.rodauth
1461
-
1462
- r.on "admin" do
1463
- rodauth.require_admin
1464
- end
1465
- end
1466
-
1467
- === Using External Features
1468
-
1469
- The +enable+ configuration method is able to load features external to
1470
- Rodauth. You need to place the external feature file where it can be
1471
- required via rodauth/features/feature_name. That file should
1472
- use the following basic structure
1473
-
1474
- module Rodauth
1475
- # :feature_name will be the argument given to enable to
1476
- # load the feature, :FeatureName is optional and will be used to
1477
- # set a constant name for prettier inspect output.
1478
- Feature.define(:feature_name, :FeatureName) do
1479
- # Shortcut for defining auth value methods with static values
1480
- auth_value_method :method_name, 1 # method_value
1481
-
1482
- auth_value_methods # one argument per auth value method
1483
-
1484
- auth_methods # one argument per auth method
1485
-
1486
- route do |r|
1487
- # This block is taken for requests to the feature's route.
1488
- # This block is evaluated in the scope of the Rodauth::Auth instance.
1489
- # r is the Roda::RodaRequest instance for the request
1490
-
1491
- r.get do
1492
- end
1493
-
1494
- r.post do
1495
- end
1496
- end
1497
-
1498
- configuration_eval do
1499
- # define additional configuration specific methods here, if any
1500
- end
1501
-
1502
- # define the default behavior for the auth_methods
1503
- # and auth_value_methods
1504
- # ...
1505
- end
1506
- end
1507
-
1508
- See the {internals guide}[rdoc-ref:doc/guides/internals.rdoc] for a more complete
1509
- example of how to construct features.
1510
-
1511
- === Overriding Route-Level Behavior
1512
-
1513
- All of Rodauth's configuration methods change the behavior of the
1514
- Rodauth::Auth instance. However, in some cases you may want to
1515
- overriding handling at the routing layer. You can do this easily
1516
- by adding an appropriate route before calling +r.rodauth+:
1517
-
1518
- route do |r|
1519
- r.post 'login' do
1520
- # Custom POST /login handling here
1521
- end
1522
-
1523
- r.rodauth
1524
- end
1525
-
1526
- === Precompiling Rodauth Templates
1527
-
1528
- Rodauth serves templates from it's gem folder. If you are using
1529
- a forking webserver and want to preload the compiled templates
1530
- to save memory, or if you are chrooting your application, you can
1531
- benefit from precompiling your rodauth templates:
1532
-
1533
- plugin :rodauth do
1534
- # ...
1535
- end
1536
- precompile_rodauth_templates
1537
-
1538
- == Ruby Support Policy
1539
-
1540
- Rodauth fully supports the currently supported versions of Ruby (MRI) and JRuby. It may
1541
- support unsupported versions of Ruby or JRuby, but such support may be dropped in any
1542
- minor version if keeping it becomes a support issue. The minimum Ruby version
1543
- required to run the current version of Rodauth is 1.9.2.
1544
-
1545
- == Similar Projects
1546
-
1547
- All of these are Rails-specific:
1548
-
1549
- * {Devise}[https://github.com/heartcombo/devise]
1550
- * {Authlogic}[https://github.com/binarylogic/authlogic]
1551
- * {Sorcery}[https://github.com/Sorcery/sorcery]
1552
-
1553
- == Author
1554
-
1555
- Jeremy Evans <code@jeremyevans.net>