A very simple user authentication
Enter your username¶
Let's toy with the idea of having users login to our CourseReVU App. For now, we just ask for their username and welcome them!
Add a form to index.hbs
to collect username:
1 2 3 4 | <form action="/" method="post"> <input type="text" placeholder="username" name="username"/> <button>Sign in</button> </form> |
The form upon submission (clicking the Sign in
button) triggers a HTTP Post request and its path is set to (return to) the homepage. This is consistent with the PRG pattern.
To handle the HTTP Post request, we need to update our controller (WebServer.main
):
1 2 3 4 5 6 | post("/", (req, res) -> { // TODO Capture the provided username // TODO Redirect to homepage }); |
Me want cookie!¶
We need to capture the provided username in HTTP Post and redirect that information to HTTP Get. We can do this by capturing req.queryParams("username");
and store it in our web-server application. It would be, however, an anti-pattern! HTTP is meant to be stateless (server should not care about the state of the client, e.g. if client is signed in or not). The generally accepted way to make HTTP appear to be stateful is by storing little bits of data (that are stored on the client) and send on each request to the server. These are called cookies.
Web Cookie
Cookies are simple text files that a website can store on your browser. The main purpose of a cookie is to identify users and possibly prepare customized Web pages or to save site login information for you.
You can set a cookie on a Response
and read it on all future Request
s.
1 2 3 4 5 6 7 | post("/", (req, res) -> { // Capture the provided username String username = req.queryParams("username"); res.cookie("username", username); // TODO Redirect to homepage }); |
1 2 3 4 5 6 7 8 | post("/", (req, res) -> { // Capture the provided username String username = req.queryParams("username"); res.cookie("username", username); // TODO Redirect to homepage res.redirect("/"); return null; }); |
Now on the HTTP Get request, we can retrieve the cookie data:
1 2 3 4 5 | get("/", (req, res) -> { Map<String, String> model = new HashMap<>(); model.put("username", req.cookie("username")); return new ModelAndView(model, "index.hbs"); }, new HandlebarsTemplateEngine()); |
Let's see what we can do with username
in index.hbs
.
Logic in template!¶
We will use a #if
block in index.hbs
to greet the user if he/she is signed in.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | {{#partial "content"}} <h1>Welcome to CourseReVU App</h1> {{#if username}} <p>You are logged in as {{ username }}.</p> {{else}} <form action="/" method="post"> <input type="text" placeholder="username" name="username"/> <button>Sign in</button> </form> {{/if}} <p>View <a href="courses">courses</a></p> {{/partial}} {{> base.hbs}} |
Rerun the WebServer
and sign in! Note that we do not ask for password nor that we check the username against a database of usernames. It is a long way from proper authentication but it is a step towards it.
Exercise¶
- Update the behavior of homepage so that it would only show the link to courses page if the user is signed in.
- Search online and figure out how you can delete the cookie (hint: use Chrome browser and figure out how to access the cookies in "Inspect Elements" of Chrome Web DevTools).