Today, we're talking cookies. Something something, joke about tasty baked goods... No. Even if you don't have much experience with programming, you likely have heard about cookies, if only because websites keep asking if they can use them. Even if you've already heard about them, it's good to have a proper understanding of what they do. Cookies are used by websites to store information on the user's side of the website experience. This allows the website to do things like; keep you logged in on return visits, remember your password, track what you're viewing, etc. Since HTTP (the go to language for websites) doesn't have a way of keeping track of any of this information by itself, cookies lets it hold onto all this information and more for use in the web browsing experience.
Baking the Cookie
I know I said no to the baking joke earlier, but I had to. Now that a basic understanding is established, we're going to be getting into the more technical side of things. For this blog post, I'll be using Ruby on Rails and React, although Rails will be the focus, but if you're going to be following along with me in an actual app, you'll need to do some things first. In order for a fresh Rails application to use cookies, you will need to go into config/application.rb
. Once there, you'll need to remove config.api_only = true
and replace it with the following:
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore
You'll also want to add in config.action_dispatch.cookies_same_site_protection = :strict
for security.
Now that the basic setup is done, we'll move onto properly utilizing cookies.
Authentication
One of the main uses for cookies is logins, so lets cover it. When you first visit a site, you log into it. Makes sense, but it would really suck if every time you leave the page, or even reload it, you'd have to re-sign in. That's where authentication comes in. Once you've logged in, the site remembers who you are, so that when it sees you again, it doesn't have to ask. Now all the annoyances of logging in over and over are gone, but how do we do that?
Let's start out really easy. We'll create a path we can post to for logging in.
post "/login", to: "sessions#create"
Looks great, but the place we're posting to, "sessions#create"
, doesn't actually exist yet. So let's make it and walkthrough what it means. (# indicates that the line is a comment)
# lets setup the thing in charge of session as a whole first
class SessionsController < ApplicationController
# now onto the create part of "sessions#create"
# this is the thing that directly handles making new users
def create
# now we'll establish the user that is currently logging in,
# set that as the current user this session, and send that
# info back to the frontend.
user = User.find_by(username: params[:username])
session[:user_id] = user.id
render json: user
end
end
That's our backend all sorted. Now our front end just needs to send a POST fetch request to "/login" with our username and we're good to go... except not quite. While this does log us in and our backend will remember us when we come back, our frontend won't. This is because our frontend and backend don't have a way of telling each that information. Let's fix that.
Just like before, we'll add in a new path that our frontend can fetch to.
get "/me", to: "users#show"
Since we're getting info instead of sending info, we use get
this time instead of post
. Now we set up our User Controller to handle "users#show"
.
class UsersController < ApplicationController
def show
# same as before we establish the current user
user = User.find_by(id: session[:user_id])
# but this time we check whether user exists
# if it does we send that, if not we send an error
if user
render json: user
else
render json: { error: "Not authorized" }, status: :unauthorized
end
end
end
Now that our backend is set up, we'll add in the following to our frontend so that it can get all that info;
useEffect(() => {
fetch("/me").then((response) => {
if (response.ok) {
response.json().then((user) => setUser(user));
}
});
}, []);
With our application now able to remember us, we can finally do things with it... Like restrict people from doing certain things.
Authorization
Time to make a VIP room! Now that our cookies established who everyone is, we can have it where only certain people are authorized to do certain things. Authorization can be used to give special features to premium members, enable admin powers, or in our case, make a VIP page that only some people can view.
Rails has a lovely beautiful tool called before_action
that allows us to filter out who can do or view whatever we choose. So in our case, if we only want authorized people to be able to "enter" our VIP room, we simply put before_action :authorize
before our VIP code. Now what if we wanted everyone to see a little bit of how much they were missing out? We can simply add skip_before_action :authorize, only: [:preview]
.
While this is just the tip of the iceberg, I hope that I've helped you understand the power of cookies and just how delicious dessert is.
Top comments (0)