User Authentication
Authentication is used to verify if the users have access to that particular part of your web application. For understanding how to implement authentication we need to understand what happens behind the scenes of a browser. Suppose we run a bank, we want only our legitimate users to access our application. We set up a login page and provide our users with their username and password which they can use to validate their claim to our webapp.
When the users submit the login form, the browser takes the username, password and sends a POST request to the webserver. The server checks this with the database and if the username and password is valid then it logs the user in.
The HTTP protocol is stateless, which means every request is unique. There is no way for identifying automatically if a request is related to another request. This brings about the problem of authentication, how then can we validate if the users have access to our webapp?
We can send the username along with each HTTP request, either in the URL via a GET request or in the POST request. But this is inefficient since for each request, the webserver would need to hit the database to validate the username, also this would mean weak security since if I know your username, I can impersonate you pretty easily and the webserver is helpless to identify this impersonation.
To solve this problems Sessions were invented, sessions need to use cookies on the browser to function. The basic idea is that the server generates a sessionID and store it in a cookie on the browser. With subsequent requests, the browser will send the sessionID along with the request, the webserver will then come to know from that sessionID if the request is a fake one or not. Also we get to know who the user is from that.
Cookies
Cookies, as we saw in a previous chapter can be used to store a key, value pair on the user's browser. We used a cookie to store the CSRF token, the cookie had the name as CSRF and value as the token.
Please don't confuse sessions with cookies. Sessions are a way of working with cookies on the server side. There is a gap of the entire Internet between sessions and cookies.
Cookies are stored in our browsers, for security reasons we need to enable the "HTTPOnly" field of our cookies, so only our webapplication can read the cookie. Otherwise the user can access the cookies using Javascript.
From the go documentation
The domain
of our cookie enables a restricted access to our cookie. A visitor goes to our fictional bank website, sbank.com and enters a username and password, a cookie is stored in the browser which only the sbank.com domain can access since we are security aware and we have set the HttpOnly field to true while setting the cookie. This means some malicious website which is set up by an attacker to intentionally target our bank isn't able to access the cookie using javascript.
One has to remember that cookie is nothing but a file stored in a user's browser, if can be accessed over HTTP by our webserver, a client browser does allow access to it through browser settings or custom javascript. The browser, after all is a platform, and we have APIs to that platform.
Sessions
A session is a series of actions performed between you and the webapp you are acting, enabled by the browser and the Internet you are using.
While generating a new session, we need to check if a sessions is already active, if so we return the same session ID rather than create a new one, if not, we generate a new session ID. Session IDs need to be sufficiently random. Of course we can't generate something totally random, but we have to ensure to generate something that nobody else can replicate, unless they have access to our private key which we use to generate our random number.
Session handling using gorilla/sessions
Till now we never used any third party library or a framework in this book, this is for the first time that we are doing so, we better use libraries for handling sessions, since security is the primary aspect of any web application it is wiser to use existing (and good) packages to manage security.
Path: ~/Tasks/sessions/sessions.go
This is the sessions package which we will use in our application.
We create a CookieStore which stores the sessions information under the "sessions" in the browser. We get the session ID stored under the session cookie and store it the session
variable. When it comes to using this function, we have the AddCommentFunc
view below which is going to handle the commenting feature of our application, it'll first check if the user has an active session and if so, it'll handle the POST request to add a comment, if not, it'll redirect the user to the login page.
Path: ~/Tasks/Views/addViews.go
The below file contains the code to login and logout of our application, we basically are going to set the "loggedin" property of our cookiestore.
Path: ~/Tasks/Views/sessionViews.go
There is a better way of handling sessions using middleware, we'll introduce that concept in the next chapter.
Users
Signing users up
The above example just hardcodes the username and password, of course we'd want people to sign up to our service. We create a user table.
For the sake of simplicity, it'll only contain ID, username, password and email.
There are two parts here, first one where we allow users to sign up, and another part where we replace the hard coded username and password in our login logic.
file: ~/Tasks/main.go
file: ~/Tasks/views/sessionViews.go
file: ~/Tasks/db/user.go
We saw TaskQuery in our chapter on DB, it is a simple wrapper around db.Exec().
Note: In a real web app, you'd want to encrypt the password and not store it in plain text, this is a dummy app which'll never see the light of the day so I am keeping it plaintext.
Login
file ~/Tasks/views/sessionViews.go
file ~/Tasks/db/user.go
Note: Since we are using gorilla/sessions, we just have to plugin the functionality that the package provides and don't have to bother about the actual implementation of sessions handling, if you are interested then by all means go ahead and checkout the source code of gorilla/sessions!
We keep resetting the password as an exercise, formulate a mechanism to resetting the password, requires us to create a user table and store some profile information, either email-ID from where we'll send a security code or by doing something else! Brainstorm!
Links
Last updated