session

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Aug 12, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package session provides Redis-backed session persistence and compact binary session encoding for authentication hot paths.

Binary encoding

Sessions are stored in Redis as a compact binary format (schema versions v1–v5) with forward migration on read. The encoder is append-only: new versions add fields but never reinterpret old ones.

Architecture boundaries

This package owns the Store (Redis operations) and the Session model. It does NOT interpret JWT tokens, evaluate permissions, or enforce authentication policy — those responsibilities belong to the Engine.

What this package must NOT do

  • Import goAuth, jwt, or permission (no upward imports).
  • Perform application-level authorization decisions.
  • Store plaintext secrets in Session fields.

Index

Constants

View Source
const (
	// CurrentSchemaVersion is the currently encoded Redis session schema version.
	CurrentSchemaVersion = 5
)

Variables

View Source
var ErrRedisUnavailable = errors.New("redis unavailable")

ErrRedisUnavailable is an exported constant or variable used by the authentication engine.

View Source
var ErrRefreshHashMismatch = errors.New("refresh hash mismatch")

ErrRefreshHashMismatch is an exported constant or variable used by the authentication engine.

View Source
var ErrRefreshSessionCorrupt = errors.New("refresh session corrupt")

ErrRefreshSessionCorrupt is returned when the refresh target session blob is invalid.

View Source
var ErrRefreshSessionExpired = errors.New("refresh session expired")

ErrRefreshSessionExpired is returned when the refresh target session is expired.

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

ErrRefreshSessionNotFound is returned when the refresh target session does not exist.

Functions

func Encode

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

Encode serializes a Session into a compact binary format (v5 wire protocol). The result is stored as the Redis value.

Performance: single allocation; ~200 bytes per session.
Docs: docs/session.md

Types

type Session

type Session struct {
	// SchemaVersion is the on-wire session schema version decoded from Redis.
	// New writes always encode with CurrentSchemaVersion.
	SchemaVersion uint8

	SessionID string
	UserID    string
	TenantID  string

	Role string

	Mask interface{}

	PermissionVersion uint32
	RoleVersion       uint32
	AccountVersion    uint32
	Status            uint8
	RefreshHash       [32]byte
	IPHash            [32]byte
	UserAgentHash     [32]byte

	CreatedAt int64
	ExpiresAt int64
}

Session is the in-memory representation of a user session. It is serialized to Redis using the v5 binary wire format via Encode/Decode.

func Decode

func Decode(data []byte) (*Session, error)

Decode deserializes the binary wire format back into a Session. Returns an error if the version byte is unsupported or the payload is truncated.

Docs: docs/session.md

type Store

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

Store is a Redis-backed session store that handles persistence, expiration, sliding window renewal, and atomic refresh-token rotation.

Docs: docs/session.md

func NewStore

func NewStore(
	redis redis.UniversalClient,
	prefix string,
	sliding bool,
	jitterEnabled bool,
	jitterRange time.Duration,
) *Store

NewStore creates a session Store backed by the given Redis client. prefix sets the Redis key namespace; slidingExp, jitterEnabled, and jitterRange control expiration behavior.

Docs: docs/session.md

func (*Store) ActiveSessionCount

func (s *Store) ActiveSessionCount(ctx context.Context, tenantID, userID string) (int, error)

ActiveSessionCount returns the number of tracked session IDs for a user in a tenant.

func (*Store) ActiveSessionIDs

func (s *Store) ActiveSessionIDs(ctx context.Context, tenantID, userID string) ([]string, error)

ActiveSessionIDs returns tracked session IDs for a user in a tenant.

func (*Store) Delete

func (s *Store) Delete(ctx context.Context, tenantID, sessionID string) error

Delete removes a session from Redis and decrements the session counter.

Performance: 2–3 Redis commands (DEL + counter decrement).
Docs: docs/session.md

func (*Store) DeleteAllForUser

func (s *Store) DeleteAllForUser(ctx context.Context, tenantID, userID string) error

DeleteAllForUser removes all sessions for a user within a tenant.

ATOMICITY NOTE: This operation is NOT fully atomic. It reads the user's session set (SMembers), checks which sessions still exist (pipeline EXISTS), then deletes them (TxPipelined DEL). A session created between the read and delete phases will not be captured by this call. In practice this race is extremely narrow and only affects logout-all semantics — the stray session will expire naturally or be caught by the next DeleteAllForUser call. Callers requiring stronger guarantees can follow up with a counter reconciliation or a second DeleteAllForUser invocation.

DeleteAllForUser may return an error when input validation, dependency calls, or security checks fail. DeleteAllForUser does not mutate shared global state and can be used concurrently when the receiver and dependencies are concurrently safe.

func (*Store) EstimateActiveSessions

func (s *Store) EstimateActiveSessions(ctx context.Context, tenantID string) (int, error)

EstimateActiveSessions scans tenant session keys and counts matches. This is an admin-only O(n) operation and must not be used in request hot paths.

func (*Store) Get

func (s *Store) Get(ctx context.Context, tenantID, sessionID string, ttl time.Duration) (*Session, error)

Get retrieves a session by tenant and session ID. Returns the decoded Session or an error if not found or Redis is unavailable.

Performance: 1 Redis GET.
Docs: docs/session.md

func (*Store) GetManyReadOnly

func (s *Store) GetManyReadOnly(ctx context.Context, tenantID string, sessionIDs []string) ([]*Session, error)

GetManyReadOnly fetches multiple sessions without mutating Redis state.

func (*Store) GetReadOnly

func (s *Store) GetReadOnly(ctx context.Context, tenantID, sessionID string) (*Session, error)

GetReadOnly fetches a session without mutating TTL, index, or any Redis state.

func (*Store) Ping

func (s *Store) Ping(ctx context.Context) (time.Duration, error)

Ping returns a point-in-time Redis availability check and latency.

func (*Store) RotateRefreshHash

func (s *Store) RotateRefreshHash(
	ctx context.Context,
	tenantID, sessionID string,
	providedHash [32]byte,
	nextHash [32]byte,
) (*Session, error)

RotateRefreshHash atomically replaces the refresh-token hash in the session using a Lua CAS script. This is the core of the rotation protocol that enables reuse detection.

Performance: 1 Lua EVALSHA (atomic compare-and-swap).
Docs: docs/session.md, docs/flows.md#refresh-token-rotation
Security: CAS prevents lost updates under concurrency.

func (*Store) Save

func (s *Store) Save(ctx context.Context, sess *Session, ttl time.Duration) error

Save persists a Session to Redis with the given TTL.

Performance: 2–3 Redis commands (SET + counter increment).
Docs: docs/session.md

func (*Store) SetTenantSessionCount

func (s *Store) SetTenantSessionCount(ctx context.Context, tenantID string, count int) error

SetTenantSessionCount sets (or clears) the tracked tenant session counter.

func (*Store) ShouldEmitDeviceAnomaly

func (s *Store) ShouldEmitDeviceAnomaly(ctx context.Context, sessionID, kind string, window time.Duration) (bool, error)

ShouldEmitDeviceAnomaly returns true only for the first anomaly in the window per session/kind.

func (*Store) TenantSessionCount

func (s *Store) TenantSessionCount(ctx context.Context, tenantID string) (int, error)

TenantSessionCount returns the tracked tenant-wide session counter.

func (*Store) TrackReplayAnomaly

func (s *Store) TrackReplayAnomaly(ctx context.Context, sessionID string, ttl time.Duration) error

TrackReplayAnomaly increments replay anomaly counter for a session ID.

Jump to

Keyboard shortcuts

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