 (defmethod destroy-session :cookie [session])
 
 ;; Session middleware
+(defn- in-seconds
+  "Returns the current time plus seconds as milliseconds."
+  [seconds]
+  (let [current-time (. System currentTimeMillis)]
+    (+ (* seconds 1000) current-time)))
+
+(defn- set-session-expires-at
+  "Updates the session :expires-at if this session has an
+   expires value, otherwise just retuns the session."
+  [session]
+  (if-let [expires (:expires *session-repo*)]
+    (assoc session :expires-at (in-seconds expires))
+    session))
+
+(defn- session-expired?
+  "True if this session's timestamp is in the past."
+  [session]
+  (if-let [expires-at (:expires-at session)]
+    (let [current-time (. System currentTimeMillis)]
+      (< expires-at current-time))
+    false))
+
+(defn- new-session
+  "Returns a new session.  Will set the expires timestamp if needed."
+  []
+  (if (contains? *session-repo* :expires)
+    (set-session-expires-at (create-session))
+    (create-session)))
+
+(defn- new-request-session
+  "Associates a new session with a request."
+  [request]
+  (assoc request
+    :session      (new-session)
+    :new-session? true))
 
 (defn- get-request-session
   "Retrieve the session using the 'session' cookie in the request."

  "Wrap a handler in a session of the specified type. Session type defaults to
  :memory if not supplied."
  ([handler]
    (with-session handler :memory))
  ([handler session-repo]
    (fn [request]
      (binding [*session-repo* session-repo]

  "Associate the session with the request."
  [request]
  (if-let [session (get-request-session request)]
    (if (session-expired? session)
      (do
        (destroy-session session)
        (new-request-session request))
      (assoc request :session (set-session-expires-at session)))
    (new-request-session request)))

(defn- assoc-request-flash
  "Associate the session flash with the request and remove it from the
