diff --git a/server/device/manager.go b/server/device/manager.go
index d6d6fa741e36a48f9601576a80459b794bde59d7..6343e79c546e37edab43483706ccefcb54b83584 100644
--- a/server/device/manager.go
+++ b/server/device/manager.go
@@ -11,22 +11,33 @@ import (
 
 	"git.autistici.org/id/auth"
 	"github.com/gorilla/securecookie"
-	"github.com/gorilla/sessions"
 	"github.com/mssola/user_agent"
 )
 
-func randomDeviceID() string {
+const (
+	deviceIDCookieName   = "_dev"
+	deviceIDCookieMaxAge = 10 * 365 * 86400
+)
+
+type DeviceID []byte
+
+func (d DeviceID) String() string {
+	return hex.EncodeToString(d)
+}
+
+func randomDeviceID() DeviceID {
 	b := make([]byte, 8)
 	if _, err := io.ReadFull(rand.Reader, b[:]); err != nil {
 		panic(err)
 	}
-	return hex.EncodeToString(b)
+	return b
 }
 
 // Manager can provide DeviceInfo entries for incoming HTTP requests.
 type Manager struct {
-	store sessions.Store
-	geodb *geoIPDb
+	sc        *securecookie.SecureCookie
+	urlPrefix string
+	geodb     *geoIPDb
 }
 
 // Config stores options for the device info manager.
@@ -52,26 +63,27 @@ func New(config *Config, urlPrefix string) (*Manager, error) {
 		config.AuthKey = string(securecookie.GenerateRandomKey(64))
 	}
 
+	sc := securecookie.New([]byte(config.AuthKey), nil)
+	sc.MaxAge(deviceIDCookieMaxAge)
+	sc.SetSerializer(securecookie.NopEncoder{})
+
 	return &Manager{
-		geodb: geodb,
-		store: newStore([]byte(config.AuthKey), urlPrefix),
+		sc:        sc,
+		geodb:     geodb,
+		urlPrefix: urlPrefix,
 	}, nil
 }
 
-const deviceIDSessionName = "_dev"
-
 // GetDeviceInfoFromRequest will retrieve or create a DeviceInfo
 // object for the given request. It will always return a valid object.
 // The ResponseWriter is needed to store the unique ID on the client
 // when a new device info object is created.
 func (m *Manager) GetDeviceInfoFromRequest(w http.ResponseWriter, req *http.Request) *auth.DeviceInfo {
-	session, _ := m.store.Get(req, deviceIDSessionName)
-	devID, ok := session.Values["id"].(string)
-	if !ok || devID == "" {
+	devID, ok := m.getDeviceCookie(req)
+	if !ok || len(devID) == 0 {
 		// Generate a new Device ID and save it on the client.
 		devID = randomDeviceID()
-		session.Values["id"] = devID
-		if err := session.Save(req, w); err != nil {
+		if err := m.setDeviceCookie(w, devID); err != nil {
 			// This is likely a misconfiguration issue, so
 			// we want to know about it.
 			log.Printf("error saving device manager session: %v", err)
@@ -82,7 +94,7 @@ func (m *Manager) GetDeviceInfoFromRequest(w http.ResponseWriter, req *http.Requ
 	ua := user_agent.New(uaStr)
 	browser, _ := ua.Browser()
 	d := auth.DeviceInfo{
-		ID:        devID,
+		ID:        devID.String(),
 		UserAgent: uaStr,
 		Mobile:    ua.Mobile(),
 		OS:        ua.OS(),
@@ -110,6 +122,33 @@ func (m *Manager) GetDeviceInfoFromRequest(w http.ResponseWriter, req *http.Requ
 	return &d
 }
 
+func (m *Manager) getDeviceCookie(r *http.Request) (DeviceID, bool) {
+	if cookie, err := r.Cookie(deviceIDCookieName); err == nil {
+		var value []byte
+		if err = m.sc.Decode(deviceIDCookieName, cookie.Value, &value); err == nil {
+			return DeviceID(value), true
+		}
+	}
+	return nil, false
+}
+
+func (m *Manager) setDeviceCookie(w http.ResponseWriter, value DeviceID) error {
+	encoded, err := m.sc.Encode(deviceIDCookieName, []byte(value))
+	if err != nil {
+		return err
+	}
+	cookie := &http.Cookie{
+		Name:     deviceIDCookieName,
+		Value:    encoded,
+		Path:     m.urlPrefix + "/",
+		Secure:   true,
+		HttpOnly: true,
+		MaxAge:   deviceIDCookieMaxAge,
+	}
+	http.SetCookie(w, cookie)
+	return nil
+}
+
 func getIPFromRequest(req *http.Request) net.IP {
 	// Parse the RemoteAddr Request field, for starters.
 	host, _, err := net.SplitHostPort(req.RemoteAddr)
diff --git a/server/device/store.go b/server/device/store.go
deleted file mode 100644
index 1a00725a0ede2be7eca7d0c1b8c7482f57744c19..0000000000000000000000000000000000000000
--- a/server/device/store.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package device
-
-import "github.com/gorilla/sessions"
-
-const aVeryLongTimeInSeconds = 10 * 365 * 86400
-
-func newStore(authKey []byte, urlPrefix string) sessions.Store {
-	// No encryption, long-term lifetime cookie.
-	store := sessions.NewCookieStore(authKey, nil)
-	store.Options = &sessions.Options{
-		Path:     urlPrefix + "/",
-		HttpOnly: true,
-		Secure:   true,
-		MaxAge:   aVeryLongTimeInSeconds,
-	}
-	return store
-}