Client-side sessions for akka-http
akka-http is an experimental Akka module, originating from spray.io, for building reactive REST services with an elegant DSL. It has almost all of the required functionalities to serve as a backend for a web (single-page-)application, with one exception: session handling. The akka-http-session project aims to fill that gap (star if you like the code / find it interesting!).
akka-http-session
provides three main features:
- client-side sessions, using session cookies, with signed content, optionally encrypted and expiring after the given period
- CSRF protection using double-submit cookies
- remember me support using persistent cookies and a server-side token store
The sessions are typed, which means that you can easily store simple case classes in the client-side session in addition to values of basic types.
Let's take a look at some code! Here we have login, logout and get-data endpoints using client-side sessions where all non-GET requests are protected against CSRF:
case class ExampleSession(username: String)
val sessionConfig = SessionConfig.default("server_secret_please_change_me")
implicit val sessionManager = new SessionManager[ExampleSession](sessionConfig)
randomTokenCsrfProtection() {
pathPrefix("api") {
path("do_login") {
post {
entity(as[String]) { body =>
logger.info(s"Logging in $body")
setSession(ExampleSession(body)) {
setNewCsrfToken() { ctx => ctx.complete("ok") }
}
}
}
} ~
path("do_logout") {
post {
requiredSession() { session => // session: ExampleSession
invalidateSession() { ctx =>
logger.info(s"Logging out $session")
ctx.complete("ok")
}
}
}
} ~
path("current_login") {
get {
requiredSession() { session => ctx =>
logger.info("Current session: " + session)
ctx.complete(session.username)
}
}
}
} ~
pathPrefix("site") {
getFromResourceDirectory("") // serve the .html and .js files
}
}
You can try this out locally by running the example; the code in the repo also contains a simple HTML page to test logging in & out, plus fetching the login-protected data.
When dealing with sessions and cookies, security is one of the main concerns. That's why the project aims to follow the current best practices, for example:
- sign the session content using a long, environment-specific secret key
- use headers as the preferred method for submitting the CSRF token (Angular-compatible)
- store remember-me token hashes, not the tokens directly
- store remember-me token selectors and token hashes separately, to prevent timing attacks
Take a look at the readme, it contains a much more comprehensive documentation on the available directives, plus a number of links explaining the possible session/cookie-handling designs and their strenghts/weaknesses.
If you like the project - star it! Also any feedback in the form of issues / PRs is always welcome!