SCS: A session manager for Go 1.7+

30th August 2016

I’ve just released SCS, a session management package for Go 1.7+. You can view it on Github.

Its design leverages Go’s new context package to automatically load and save session data via middleware.

Importantly, it also provides the security features that you need when using server-side session stores (like straightforward session token regeneration) and supports both absolute and inactivity timeouts. The session data is safe for concurrent use.

A simple example

SCS is broken up into small single-purpose packages for ease of use. You should install the session package and your choice of session storage engine from the following table:

Package
session Provides session management middleware and helpers for
manipulating session data
engine/memstore In-memory storage engine
engine/cookiestore Encrypted-cookie based storage engine
engine/pgstore PostgreSQL based storage eninge
engine/mysqlstore MySQL based storage engine
engine/redisstore Redis based storage engine

For example:

$ go get github.com/alexedwards/scs/session
$ go get github.com/alexedwards/scs/engine/memstore

Usage is then simple:

File: main.go
package main

import (
    "io"
    "net/http"

    "github.com/alexedwards/scs/engine/memstore"
    "github.com/alexedwards/scs/session"
)

func main() {
    // Create the session manager middleware, passing in a new storage
    // engine instance as the first parameter.
    sessionManager := session.Manage(memstore.New(0))

    // Set up your HTTP handlers in the normal way.
    mux := http.NewServeMux()
    mux.HandleFunc("/put", putHandler)
    mux.HandleFunc("/get", getHandler)

    // Wrap your handlers with the session manager middleware.
    http.ListenAndServe(":4000", sessionManager(mux))
}

func putHandler(w http.ResponseWriter, r *http.Request) {
    // Use the PutString helper to add a new key and associated string value
    // to the session data. Helpers for other types are included.
    err := session.PutString(r, "message", "Hello from a session!")
    if err != nil {
        http.Error(w, err.Error(), 500)
    }
}

func getHandler(w http.ResponseWriter, r *http.Request) {
    // Use the GetString helper to retrieve the value associated with the
    // "message" key.
    msg, err := session.GetString(r, "message")
    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }
    io.WriteString(w, msg)
}

You should be able to verify that the session data is being across requests with curl:

$ curl -i -c cookies localhost:4000/put
HTTP/1.1 200 OK
Set-Cookie: scs.session.token=uts3FRcCMOIXpyx5uZx28Y54uUFRHxgtYhbgD4epeI4; Path=/; HttpOnly
Date: Tue, 30 Aug 2016 17:37:12 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8

$ curl -i -b cookies localhost:4000/get
HTTP/1.1 200 OK
Date: Tue, 30 Aug 2016 17:37:21 GMT
Content-Length: 21
Content-Type: text/plain; charset=utf-8

Hello from a session!

The complete godocs are here.

I’d love to hear any feedback – either drop me an email or open an issue on Github.

Filed under: golang

All code snippets in this post are made available to freely use under the MIT Licence.

Tweet