DHH recently posted the followings in an issue titled Add basic authentication generator.
Rails now include all the key building blocks needed to do basic authentication, but many new developers are still uncertain of how to put them together, so they end up leaning on all-in-one gems that hide the mechanics.
To address this, Rails 8 has introduced a generator that simplifies the addition of basic authentication to Rails applications. In this blog post, we'll explore the components included in this authentication scaffold.
To set up a basic authentication system in your Rails application, execute the following code.
bin/rails generate authentication
This command generates a set of essential files that provide a foundational start for implementing authentication, including support for database-tracked sessions and password reset functionality. Here is the gist of the generated scaffold.
Let’s examine the components created by the authentication generator.
To lay the groundwork for handling user accounts and session management, the
models
User
,
Current
and
Session
are set up along with their corresponding migrations. This setup includes:
CreateUsers
migration: It creates a users
table, with a uniquely indexed email_address
field and password_digest
for storing the securely hashed passwords using
has_secure_password
.
CreateSessions
migration: It sets up the sessions
table, which includes a unique token
field, along with ip_address
and user_agent
fields to record the user's
device and network details. The Session
model uses
has_secure_token
to generate unique session tokens.
The Current
model manages per-request state and provides access to the
current user's information through a delegated user
method.
Additionally, the bcrypt gem is
added to the Gemfile. If this gem is not present, it is added; if it is
commented, it is uncommented, and then bundle install
is run to install the
gem.
The core authentication logic and session management are encapsulated in the
Authentication
concern.
require_authentication
: This is a before_action
callback which attempts to
restore an existing session with resume_session
. If no session is found, it
redirects the user to the login page using request_authentication
.
resume_session
: Retrieves a session using a signed token from the cookie via
the find_session_by_cookie
method. Sets it as the current session, and saves
the token in a permanent, HTTP-only cookie using the set_current_session
method.
authenticated?
: A helper method that checks if the current user has an
active session.
allow_unauthenticated_access
: This class method allows specific actions to
bypass the require_authentication
callback.
after_authentication_url
: Returns the URL to redirect to after
authentication.
start_new_session_for(user)
: Creates a new session for the given user with
details of the user's device and IP address and then sets the current session.
terminate_session
: Destroys the current session and removes the session
token from cookies.
The
SessionsController
handles user session management and includes the following actions:
new
: Renders a login form for the user credentials. The
new.html.erb
file includes fields for email and password, displays flash messages for
success and errors, and provides a link for password recovery.
create
: Authenticates the user with the provided credentials. On success, it
creates a new session and redirects to the after_authentication_url
; on
failure, it redirects to the login form with an error message.
destroy
: Terminates the user’s session and redirects to the login form.
Combining all of this, a basic authentication flow would look like this.
The basic password reset functionality includes initiating a password reset
request, dispatching reset instructions via email, and updating the password.
The
PasswordsController
manages these actions as follows:
new
: Displays the form to request a password reset using the
new.html.erb
template.
create
: Handles the reset request, sends a reset email via the
PasswordMailer
if the user exists, and redirects with a notice. This email contains a link to
the password reset page, which includes a password_reset_token
as a
parameter. The password_reset_token
is part of the
newly added configuration to
has_secure_password
. It has a default expiration period of 15 minutes.
edit
: Renders the
edit.html.erb
template to set a new password.
update
: Updates the user's password, redirects on success, or shows an alert
on failure.
set_user_by_token
: It is the before_action
callback for the edit
and
update
actions which retrieves the user based on the password_reset_token
provided in the request parameters, ensuring proper identification of the
user.
Putting these together, the flow of resetting password would be as follows:
The current authentication generator supports email-password login for existing users but does not handle new account creation. Future updates may incorporate user account creation and other customizations.
Please check out the following pull requests for more details:
If this blog was helpful, check out our full blog archive.