redissession

package module
v1.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 25, 2025 License: MIT Imports: 17 Imported by: 0

README

RedisSession

A Redis-backed, encrypted, thread-safe HTTP session store for Go.

  • Focuses on correctness, simplicity, and practical defaults
  • Uses go-redis v9 and modern AEAD ciphers (AES-GCM, ChaCha20-Poly1305, XChaCha20-Poly1305)
  • Thread-safe session container to prevent concurrent access issues
  • Minimal external dependencies

Install

go get github.com/found-cake/redissession

Go version: see go.mod (currently Go 1.24).


Quick start

package main

import (
	"net/http"
	"time"

	"github.com/found-cake/redissession"
	"github.com/redis/go-redis/v9"
)

func main() {
	// 1) Create an AEAD cipher
	encKey, _ := redissession.GenerateKey(32) // 32 bytes for AES-256-GCM or (X)ChaCha20-Poly1305
	aead, _ := redissession.NewAESGCM(encKey)

	// 2) Build Crypto (no extra signing key needed; AEAD is authenticated)
	crypto := redissession.NewCrypto(aead, nil)

	// 3) Redis client (go-redis v9)
	client := redis.NewClient(&redis.Options{
		Addr: "127.0.0.1:6379",
		DB:   0,
	})

	// 4) Cookie options
	opts := redissession.DefaultCookieOptions()
	opts.Secure = true          // set false only for local HTTP
	opts.SameSite = http.SameSiteLaxMode
	opts.MaxAge = 3600          // 1 hour in seconds

	// 5) Create the store
	store := redissession.NewRedisStore(client, "app:", crypto, opts)

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		// Load or create a session named "app_session"
		sess, err := store.New(r, "app_session")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		// Use the session
		if sess.IsNew() {
			sess.Set("visits", 1)
		} else {
			if v, ok := sess.Get("visits").(int); ok {
				sess.Set("visits", v+1)
			}
		}

		// Optional: sliding expiration
		sess.Refresh(time.Duration(opts.MaxAge) * time.Second)

		// Save to Redis and set cookie
		if err := store.Save(r, w, sess); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.WriteHeader(http.StatusOK)
		w.Write([]byte("OK"))
	})

	http.ListenAndServe(":8080", nil)
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrSessionNotFound = errors.New("session not found")

	ErrStoreNotFound = errors.New("store not found")

	ErrInvalidSessionData = errors.New("invalid session data")

	ErrEncryptionFailed = errors.New("encryption/decryption failed")

	ErrSignatureInvalid = errors.New("signature verification failed")

	ErrSessionExpired = errors.New("session expired")

	ErrInvalidConfiguration = errors.New("invalid configuration")
)

Functions

func GenerateKey

func GenerateKey(length int) ([]byte, error)

func NewAESGCM

func NewAESGCM(key []byte) (cipher.AEAD, error)

func NewChaCha20Poly1305

func NewChaCha20Poly1305(key []byte) (cipher.AEAD, error)

func NewXChaCha20Poly1305

func NewXChaCha20Poly1305(key []byte) (cipher.AEAD, error)

func WithStore added in v1.0.1

func WithStore(r *http.Request, store *RedisStore) *http.Request

Types

type CookieOptions

type CookieOptions struct {
	Path        string
	Domain      string
	MaxAge      int // seconds
	Secure      bool
	HttpOnly    bool
	Partitioned bool
	SameSite    http.SameSite
}

func DefaultCookieOptions

func DefaultCookieOptions() *CookieOptions

func (*CookieOptions) NewCookie

func (options *CookieOptions) NewCookie(session *Session) *http.Cookie

func (*CookieOptions) RemoveCookie

func (options *CookieOptions) RemoveCookie(name string) *http.Cookie

type Crypto

type Crypto struct {
	// contains filtered or unexported fields
}

func NewCrypto

func NewCrypto(aead cipher.AEAD, signingKey []byte) *Crypto

func (*Crypto) DecryptAndVerify

func (c *Crypto) DecryptAndVerify(encryptedData string, dest interface{}, aad []byte) error

func (*Crypto) EncryptAndSign

func (c *Crypto) EncryptAndSign(data interface{}, aad []byte) (string, error)

func (*Crypto) GenerateSessionID

func (c *Crypto) GenerateSessionID() (string, error)

func (*Crypto) RandReadFull added in v1.1.0

func (c *Crypto) RandReadFull(b []byte) error

func (*Crypto) SetBackoff added in v1.1.0

func (c *Crypto) SetBackoff(d time.Duration)

func (*Crypto) SetRandRetries added in v1.1.0

func (c *Crypto) SetRandRetries(retries int)

type RedisStore

type RedisStore struct {
	// contains filtered or unexported fields
}

func GetStore

func GetStore(r *http.Request) (*RedisStore, error)

func NewRedisStore

func NewRedisStore(client *redis.Client, keyPrefix string, crypto *Crypto, options *CookieOptions) *RedisStore

func (*RedisStore) Destroy

func (s *RedisStore) Destroy(r *http.Request, w http.ResponseWriter, session *Session) error

func (*RedisStore) Get

func (s *RedisStore) Get(r *http.Request, name string) (*Session, error)

func (*RedisStore) New

func (s *RedisStore) New(r *http.Request, name string) (*Session, error)

func (*RedisStore) RotateID

func (s *RedisStore) RotateID(r *http.Request, w http.ResponseWriter, session *Session) error

func (*RedisStore) Save

func (s *RedisStore) Save(r *http.Request, w http.ResponseWriter, session *Session) error

type Session

type Session struct {
	// contains filtered or unexported fields
}

func NewSession

func NewSession(id string, maxAge time.Duration) *Session

func (*Session) CreatedAt

func (s *Session) CreatedAt() time.Time

func (*Session) Delete

func (s *Session) Delete(key string)

func (*Session) Destroy added in v1.0.2

func (s *Session) Destroy(r *http.Request, w http.ResponseWriter) error

func (*Session) ExpiresAt

func (s *Session) ExpiresAt() time.Time

func (*Session) Extend

func (s *Session) Extend(delta time.Duration)

func (*Session) Get

func (s *Session) Get(key string) interface{}

func (*Session) ID

func (s *Session) ID() string

func (*Session) IsNew

func (s *Session) IsNew() bool

func (*Session) MarshalJSON

func (s *Session) MarshalJSON() ([]byte, error)

func (*Session) Name

func (s *Session) Name() string

func (*Session) Refresh

func (s *Session) Refresh(maxAge time.Duration)

func (*Session) RotateID added in v1.0.2

func (s *Session) RotateID(r *http.Request, w http.ResponseWriter) error

func (*Session) Save

func (s *Session) Save(r *http.Request, w http.ResponseWriter) error

func (*Session) Set

func (s *Session) Set(key string, val interface{})

func (*Session) UnmarshalJSON

func (s *Session) UnmarshalJSON(b []byte) error

func (*Session) UpdatedAt

func (s *Session) UpdatedAt() time.Time

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL