Session Expiry in Vapor 4

Viewed 169

I am developing a web application with Vapor 4. It would be useful to persist client-made data on the server side for a few minutes at a time in between requests. I want to use sessions to do this. However, I am a bit confused on how the best way to automatically destroy this data after a set time. Should I make a job and have it check periodically? Or is there an easy way to set an expiry time on session creation?

1 Answers

I have used a bit of Middleware to achieve this for some months and it is very reliable.

It compares the timestamp now to the value from the immediate previous request. If the difference is greater than the allowed session timeout, it forces a logout.

I had to give a bit of thought to initialising the timestamp and "BAD" ensures a nil gets returned from trying to initialise a Double, which then gets the current timestamp to start the session 'timer'. I think this is safe as the user can't log in without having made at least one route call beforehand and I have other Middleware that checks to make sure the user is logged in. Try this:

struct SessionTimeoutMiddleware:Middleware
{
    func respond(to request:Request, chainingTo next:Responder) -> EventLoopFuture<Response>
    {
        let lastRequestTimeStamp = Double(request.session.data["lastRequest"] ?? "BAD") ?? Date().timeIntervalSince1970
        request.session.data["lastRequest"] = String(Date().timeIntervalSince1970)
        if Date().timeIntervalSince1970 - lastRequestTimeStamp > 300.0 // seconds
        {
            request.auth.logout(User.self)
            return request.eventLoop.makeSucceededFuture(request.redirect(to:"/somewhere/safe"))
        }
        return next.respond(to:request)
    }
}

Then, register in configure.swift using:

let userAuthSessionsMW = User.authenticator()
let sessionTimeoutMW = SessionTimeoutMiddleware()
let timed = app.grouped(C.URI.Users).grouped(userAuthSessionsMW, sessionTimeoutMW)
try SecureRoutes(timed)
Related