#Authentication, Logging in and Authorization in our app so far
###Authentication
Authentication in our app is fairly straightforward, at this point. In our gemfile, we require the gem 'bcrypt', and in our User model, we include the method
has secure password
. This tells the gem to look at the users table for the password_digest
column that we need for the 'salted' or encoded version of our password.
We ask a user to input a password when they create their account. They also must input a confirmation for their password. Bcrypt looks at the password and password confirmation params, and if they match, it encodes the password into an enormous string of symbols and letters, (this is based off an algorithm, and it is equal to the password originally input). The original password isn't stored anywhere. When a user logs in, Bcrypt checks the database to make sure the encoded version of what the user enters upon login matches what's on the able. If that's the case, they are authenticated and logged in.
###What does 'logged in' actually mean to us?
To understand the concept of logging in to our app, we have to understand the concept of sessions
first. A session
is a temporary hash that a user 'carries' throughout their visit to the site. This hash disappears once they leave the site or close the browser; their session has ended.
In our app, logging in really just means having a user_id
key and value set in the sessions hash. However, we don't set that key and value until we have done two things: look up the user to see if they exist in the database, and check that their password is correct.
Conversely, a user 'logs out' by clicking a link that simply sets the user_id
key in their session
to nil, or deletes the key entirely.
###Authorization
Authorization is a tricky concept, and it's going to be important for our app to be considered MVP.
At this stage, we are using essentially the same methods that PJ wrote yesterday to ensure that users can only view their own information, and not 'cheat the routes', so to speak. Their are a handful of methods, in the application_controller
and and users_controller
that we use to accomplish this.
In our application_controller
, we've defined two methods, current_user
and logged_in?
These two methods are in our application controller because we are presumably going to be calling them frequently, and in many different controllers.
######current_user
def current_user
@current_user ||= User.find_by(id: session[:user_id])
end
This method simply sets the current_user
to the 'current user' from session
, buy only if it hasn't already been established.
######logged_in?
def logged_in?
current_user.present?
end
This method simply checks that the current_user
(already established in the above method), is actually logged in, and not nil.
Our users_controller
contains three more private methods to control how we authorize users on our site (so far)
######load_user
def load_user
@user = User.find(params[:id])
redirect_to root_path if !@user
end
load_user
is a method that establishes what user is being accessed based of the URL in the browser (hence the reference to params
)
The key thing to understand here is that the user being accessed through params
is NOT necessarily that user! ANYONE can type that route into the browser and attempt to access the information there!
######authenticate
def authenticate
redirect_to root_path if !logged_in?
end
authenticate
simply checks that the logged_in
method is returning true, and redirects the user back home if it's not. This prevents users that haven't logged in at all from randomly accessing routes.
######authorize
def authorize
if current_user != @user #here we are making sure that the user coming from params is the same as the user in params
redirect_to user_path(current_user)
end
end
This method checks that the current_user
(the user that is logged in, determined by session
), is the same as the @user
that we loaded earlier (which was based off params). If they aren't the same, the user is bounced back to their own show route, and never sees the route they were attempting to access.
#######before_action
The users_controller
also uses a few before_action
s to control what happens before a user can view any route under the users controller
before_action :load_user, only: [:show, :edit, :destroy, :update,]
before_action :authenticate, :authorize
Finally, if we look at our show
action, we can see that the @user
is simply established as the user from params in the erb rendered henceforth. However, the browser will never hit that action if they are bounced away from the action by one of the redirects included in the methods in before_action