reference:
https://www.railstutorial.org/book/advanced_login
https://www.theodinproject.com/courses/ruby-on-rails/lessons/sessions-cookies-and-authentication
Session
HTTP is a stateless protocol, treating each request as an independent transaction that is unable to use information from any previous requests. This means there is no way within the hypertext transfer protocol to remember a user’s identity from page to page; instead, web applications requiring user login must use a session.
Session:
Is a semi-permanent connection between two computers (such as a client computer running a web browser and a server running Rails). A session is just a place to store data during one request that you can read during later requests.
The most common techniques for implementing sessions in Rails involve using cookies.
cookies:
Pros: Because cookies persist from one page to the next, they can store information (such as a user id) and user preference on the user's browser. Cookies are key-value data pairs that are stored in the user’s browser until they reach their specified expiration date.
Cons: You shouldn’t store anything in regular browser cookies that needs to either be secure. It’s too easy for users to clear their cache and/or steal/manipulate unsecured cookies.
Develop: Because cookies became more and more useful, developer tends to store more info in the cookies. Later, they use cookies to store a identifier and store the actual info in their database. When user logs in, they send their unique cookie identifier and the server will look it up in their db.
Rails: To work with cookies, Rails gives you access to a special hash called cookies
, where each key-value pair is stored as a separate cookie on the user’s browser.
With each new request to your server, the browser will send along all the cookies and you can access them in your controllers and views like a normal hash.
It’s convenient to model sessions as a RESTful resource. Unlike the Users resource, which uses a database back-end (via the User model) to persist data, the Sessions resource will use cookies, and much of the work involved in login comes from building this cookie-based authentication machinery.
RESTful resource:
visiting the login page will render a form for new sessions, logging in will create a session, and logging out will destroy it.
Logging in: Send aPOST
request to the create
action
Logging out: Send aDELETE
request to the destroy
action.
Login form (Currently, closing window will logout users)
Action of the form --> Post to the URL/users
<% provide(:title, "Log in") %>
<h1>Log in</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(:session, url: login_path) do |f| %>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.submit "Log in", class: "btn btn-primary" %>
<% end %>
<p>New user? <%= link_to "Sign up now!", signup_path %></p>
</div>
</div>
Finding and authenticating a user
the submission results in a params
hash containing the email and password under the key session
, which (omitting some irrelevant details used internally by Rails) appears as follows:
session:
email: '[email protected]'
password: 'foobar'
commit: Log in
action: create
controller: sessions
In other words, inside the create
action the params
hash has all the information needed to authenticate users by email and password.
class SessionsController < ApplicationController
skip_before_action :authorize
def new
end
def create
//pulls the user out of the database using the submitted email address
if user = User.find_by_user_name(params[:name]) // method defined in User controller
if user.authenticate(params[:password]) // method defined in User controller
session[:user_id] = user.id
redirect_to quads_url
else
redirect_to login_url, :alert => "Invalid password combination. Try again."
end
else
redirect_to login_url, :alert => "User doesn't exist."
end
end
def destroy
session[:user_id] = nil
redirect_to login_url, :notice => "Logged out"
end
end
Logging in
In this section, we’ll log the user in with a temporary session cookie that expires automatically upon browser close.
This places a temporary cookie on the user’s browser containing an encrypted version of the user’s id.
In contrast to the persistent cookie created by the cookies
method. the temporary cookie created by the session
method expires immediately when the browser is closed.
Because temporary cookies created using the session
method are automatically encrypted. This applies only to temporary sessions initiated with the session
method, though, and is _not _the case for persistent sessions created using the cookies
method.
Logging out
using a destroy
action to delete sessions
After logging in, we use delete
to issue a DELETE
request to the logout path and verify that the user is logged out
Conclusion
Rails can maintain state from one page to the next using temporary cookies via the
session
method.The login form is designed to create a new session to log a user in.
Using the
session
method, we can securely place a user id on the browser to create a temporary session.We can change features such as links on the layouts based on login status.
Remember me
Use cookies to implement "remember me".
information stored using session
is automatically secure, but this is not the case with information stored usingcookies
.In particular, persistent cookies are vulnerable to session hijacking, in which an attacker uses a stolen remember token to log in as a particular user.
creating persistent sessions appears as follows:
- Create a token: a random string of digits
- token --> cookies: Place the token in the browser cookies with an expiration date far in the future.
- Save the hash digest of the token to the database instead of the token itself.
- Place an encrypted version of the user’s id in the browser cookies.
- When presented with a cookie containing a persistent user id, find the user in the database using the given id, and verify that the remember token cookie matches the associated hash digest from the database.
Digest Access Authentication: It applies a hash function to the username and password before sending them over the network.
cookies: token + encrypted version of user id
server: hash digest of the token
Forgetting users
- Update the remember digest with
nil
- Delete the session’s user id
- Remove the permanent cookie from the browser.
Conclusion
Rails can maintain state from one page to the next using persistent cookies via the
cookies
method.We associate to each user a remember token and a corresponding remember digest for use in persistent sessions.
Using the
cookies
method, we create a persistent session by placing a permanent remember token cookie on the browser.Login status is determined by the presence of a current user based on the temporary session’s user id or the permanent session’s unique remember token.
The application signs users out by deleting the session’s user id and removing the permanent cookie from the browser.