Enforce secure session expiration time
import play.api.mvc._
class HomeController @Inject()(val controllerComponents: ControllerComponents) extends BaseController {
def index() = Action { implicit request: Request[AnyContent] =>
Ok("Welcome!").withSession("user" -> "username")
}
}
The Play Framework provides an easy way to deal with HTTP sessions. In the above code, a new session is started whenever the 'index' endpoint is hit. The session is associated with the key 'user' and the value 'username'.
However, the problem with this code is that the session does not expire after a certain period of inactivity. In this case, the session remains active indefinitely until the server is restarted or the user logs out. This is a security vulnerability because if an attacker gets hold of a user's session, they can use it to impersonate the user for an unlimited amount of time.
The vulnerability lies in the absence of a session expiration time, which should be set to ensure that sessions automatically expire after a certain period of inactivity. In this case, the requirement is for sessions to expire after 5 minutes of inactivity.
import play.api.mvc._
import play.api.libs.typedmap.TypedKey
import java.time.{Instant, Duration}
class HomeController @Inject()(val controllerComponents: ControllerComponents) extends BaseController {
// Define a key to store the last activity time in the session
val LastActivityTime: TypedKey[Instant] = TypedKey[Instant]("lastActivityTime")
def index() = Action { implicit request: Request[AnyContent] =>
val now = Instant.now()
val lastActivityTime = request.attrs.get(LastActivityTime).getOrElse(now)
val duration = Duration.between(lastActivityTime, now)
if (duration.toMinutes > 5) {
Unauthorized("Session expired")
} else {
Ok("Welcome!").withSession("user" -> "username").addingToSession(LastActivityTime -> now.toString)
}
}
}
The updated code introduces a mechanism to track the last activity time of a user session. This is done by storing the last activity time in the session using the
TypedKey
LastActivityTime
.
In the
index
action, we first get the current time (
now
) and then retrieve the last activity time from the session. If there is no last activity time stored in the session (which would be the case for a new session), we use the current time as the last activity time.
Next, we calculate the duration between the last activity time and the current time. If this duration is more than 5 minutes, we return an
Unauthorized
response, effectively ending the session. If the duration is 5 minutes or less, we update the session with the current time as the new last activity time and return a
Ok
response.
This way, we ensure that user sessions expire after 5 minutes of inactivity, addressing the identified vulnerability.