Remembrance of Things Past

Basic authentication is a lightweight solution to general authentication, but what if we need to remember a little more information about a user’s session? That’s where cookies come in.

Let’s build on our authenticated application and add support for simple cookie handling.

sourceimport unfiltered.Cookie

case class App(users: Users) extends
unfiltered.filter.Plan {
  def intent = Auth(users) {
    case Path("/") & Cookies(cookies) =>
      ResponseString(cookies("pref") match {
        case Some(c: Cookie) =>
          s"you pref ${c.value}, don't you?"
        case _ => "no preference?"
      })
    case Path("/prefer") & Params(p) =>
      // let's store it on the client
      SetCookies(Cookie("pref", p("pref")(0))) ~>
        Redirect("/")
    case Path("/forget") =>
      SetCookies(Cookie("pref", "")) ~>
        Redirect("/")
  }
}

Now that we have a slightly more sophisitcated basic application let’s mount it with a user named jim and a password of j@m.

sourceobject JimsAuth extends Users {
  def auth(u: String, p: String) =
    u == "jim" && p == "j@m"
}

val binding = SocketPortBinding(host = "localhost", port = 8080)

unfiltered.jetty.Server.portBinding(binding).plan(
  App(JimsAuth)
).run()

In your browser, open the url http://localhost:8080/ and you should be greeted with its native authentication dialog. Enter jim and j@m, if you are feeling authentic.

Once authenticated you should see simple text questioning your preferences. Why is this? Well, you have yet to tell the server what you prefer. In your url bar, enter the address

http://localhost:8080/prefer?pref=kittens

or whatever else you have a preference for. Now, every time you request http://localhost:8080/ the server has remembered your preference for you. This is a cookie at work!

If you change your mind you can always hit the prefer path with a new pref or just tell the server to forget it by entering the address http://localhost:8080/forget.

The source code for this page can be found here.