Add Session Management
Set up session middleware to manage your application's authenticated sessions.
To manage the user's authenticated state, you'll need to implement a session manager for your application. Unlike other Wristband SDKs that provide built-in session middleware, the Go SDK is unopinionated about session storage, giving you full control over how sessions are stored and managed.
The SDK defines a SessionManager interface that you need to implement. The session data is typically stored in an encrypted cookie, and on subsequent requests, the middleware decrypts the cookie and restores the session state.
Session Manager Interface
The SessionManager interface defines three methods that your implementation must provide:
type SessionManager interface {
StoreSession(w http.ResponseWriter, r *http.Request, session *goauth.Session) error
GetSession(r *http.Request) (*goauth.Session, error)
ClearSession(w http.ResponseWriter, r *http.Request) error
}Lightweight Cookie Session Manager
Here is a minimal implementation of a SessionManager implementation using github.com/gorilla/securecookie and github.com/gorilla/sessions.
Run the following
go get github.com/gorilla/sessionsCode
// session.go
package main
import (
"encoding/json"
"errors"
"net/http"
"github.com/gorilla/sessions"
goauth "github.com/wristband-dev/go-auth"
)
const (
// SessionName is the name used for the session cookie
SessionName = "session"
// SessionKey is the key used to store auth data in the session
SessionKey = "auth_session"
)
// GorillaSessionManager implements the goauth.SessionManager interface
// using gorilla/sessions for session management
type GorillaSessionManager struct {
store sessions.Store
}
func NewStore(secret []byte, secureCookies bool) goauth.SessionManager {
store := sessions.NewCookieStore(secret, nil)
store.Options.Secure = secureCookies
store.Options.HttpOnly = true
store.Options.SameSite = http.SameSiteLaxMode
return &GorillaSessionManager{
store: store,
}
}
// StoreSession implements the goauth.SessionManager interface
func (m *GorillaSessionManager) StoreSession(w http.ResponseWriter, r *http.Request, session *goauth.Session) error {
// Get existing session or create a new one
sess, err := m.store.Get(r, SessionName)
if err != nil {
// If there's an error getting the session, create a new one
// This can happen if the session was tampered with or is invalid
sess, err = m.store.New(r, SessionName)
if err != nil {
return err
}
}
// Serialize the session to JSON
sessionJSON, err := json.Marshal(session)
if err != nil {
return err
}
// Store the serialized session in the session store
sess.Values[SessionKey] = string(sessionJSON)
// Save the session
return sess.Save(r, w)
}
// GetSession implements the goauth.SessionManager interface
func (m *GorillaSessionManager) GetSession(r *http.Request) (*goauth.Session, error) {
// Get existing session
sess, err := m.store.Get(r, SessionName)
if err != nil {
return nil, err
}
// Check if the session contains auth data
sessionJSON, ok := sess.Values[SessionKey]
if !ok {
return nil, errors.New("no auth session found")
}
// Parse the serialized session
var authSession goauth.Session
err = json.Unmarshal([]byte(sessionJSON.(string)), &authSession)
if err != nil {
return nil, err
}
return &authSession, nil
}
// ClearSession implements the goauth.SessionManager interface
func (m *GorillaSessionManager) ClearSession(w http.ResponseWriter, r *http.Request) error {
// Get existing session
sess, err := m.store.Get(r, SessionName)
if err != nil {
// If we can't get the session, that's fine - we wanted to clear it anyway
return nil
}
// Remove the auth data from the session
delete(sess.Values, SessionKey)
// Set session to expire
sess.Options.MaxAge = -1
// Save the session
return sess.Save(r, w)
}Register the Session Manager
After creating your session manager implementation, you'll use it when creating the Wristband app instance:
Important: You must provide a 32-byte secret for encryption. You can generate a secure secret using 1Password's password generator .
Disabling Secure Session Cookies in Local DevelopmentBy default, session cookies are marked as secure, meaning they are only sent over HTTPS connections. Most browsers make an exception for localhost and allow secure cookies to be sent over HTTP (e.g., http://localhost). However, some browsers, such as Safari, enforce stricter rules and never send secure cookies over HTTP, even for localhost.
If you need to disable the secure flag for local development, set
secure: falsein your session options. However, be sure to restoresecure: truein production to protect session data.
// main.go
func main() {
cfg := goauth.NewAuthConfig(
"<WRISTBAND_CLIENT_ID>",
"<WRISTBAND_CLIENT_SECRET>",
"<WRISTBAND_APPLICATION_VANITY_DOMAIN>",
)
auth, err := cfg.WristbandAuth()
if err != nil {
// Handle error
}
// Create session manager
secret := os.Getenv("SESSION_SECRET")
sessionManager, err := NewCookieSessionManager(secret, true)
if err != nil {
log.Fatal(err)
}
// Create the Wristband app with the session manager
app := wristbandAuth.NewApp(sessionManager)
}// main.go
func main() {
cfg := goauth.NewAuthConfig(
"<WRISTBAND_CLIENT_ID>",
"<WRISTBAND_CLIENT_SECRET>",
"<WRISTBAND_APPLICATION_VANITY_DOMAIN>",
goauth.WithDangerouslyDisableSecureCookies(),
)
auth, err := cfg.WristbandAuth()
if err != nil {
// Handle error
}
// Create session manager
secret := os.Getenv("SESSION_SECRET")
sessionManager, err := NewCookieSessionManager(secret, false)
if err != nil {
log.Fatal(err)
}
// Create the Wristband app with the session manager
app := wristbandAuth.NewApp(sessionManager)
}Updated 2 days ago
Next, you'll use the Wristband SDK to create the necessary authentication endpoints in your Go server.