Help us shape the future of Go! Take the 2026 Go Developer Survey

usersession

package
v1.21.2 Latest Latest
Warning

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

Go to latest
Published: Oct 27, 2026 License: GPL-3.0 Imports: 12 Imported by: 0

Documentation

Overview

Package usersession issues, validates and ends user sessions. A session is a signed token plus a Redis record under its session id. Every token also carries the user's session epoch from when it was issued; revoking replaces the epoch, which invalidates every token issued before. Password changes and resets revoke, so a stolen session does not outlive them. A sign-in reads the epoch before it checks the credential and gets its session only if the epoch is still the same, so a revocation racing the sign-in does not leave a valid session behind either.

Index

Constants

View Source
const (
	UserIDClaim    = "UserId"
	SessionIDClaim = "SessionId"
	LoginTypeClaim = "LoginType"
	// EpochClaim carries the user's session epoch.
	EpochClaim = "SessionEpoch"
)

The claims of a session token.

Variables

View Source
var (
	// ErrUnavailable reports a missing session store.
	ErrUnavailable = errors.New("user session store unavailable")
	// ErrInvalidToken reports a token whose signature or lifetime does not
	// verify.
	ErrInvalidToken = errors.New("session token is invalid or expired")
	// ErrNotSession reports a verified token that is not a session: other
	// tokens, order event tickets for one, are signed with the same secret.
	ErrNotSession = errors.New("token is not a session")
	// ErrEnded reports a session that was ended or has expired.
	ErrEnded = errors.New("session ended")
	// ErrRevoked reports a session issued before the user's latest
	// revocation.
	ErrRevoked = errors.New("session revoked")
	// ErrEpochMoved reports a sign-in whose credential check a revocation
	// overtook: the epoch read before the check is no longer the current
	// one, so no session is issued.
	ErrEpochMoved = errors.New("user sessions were revoked during sign-in")
	// ErrDeviceSession reports device claims that are malformed or missing
	// from a device session; the client has to sign in again.
	ErrDeviceSession = errors.New("device session must be renewed")
	// ErrDeviceRevoked reports a device session whose device was revoked.
	ErrDeviceRevoked = errors.New("device session revoked")
)

Functions

func AcquireEpoch

func AcquireEpoch(ctx context.Context, client Store, userID int64) (string, error)

AcquireEpoch returns the epoch a new session of the user carries, creating it on first use. The key never expires: an evicted epoch fails every token that carries one closed.

func Check

func Check(claims map[string]any, current string) error

Check reports whether a token's claims are still valid against the user's current epoch (empty when none is stored). A token issued before epochs existed carries none and stays valid until the user is first revoked.

func End

func End(ctx context.Context, client Deleter, sessionID string) error

End ends one session; the user's other sessions stay valid.

func Issue

func Issue(ctx context.Context, client Store, secret string, lifetime int64, grant Grant) (string, error)

Issue signs a session token for grant that lives for lifetime seconds and records the session.

func Key

func Key(userID int64) string

Key is the Redis key holding the user's session epoch; validation reads it together with the session itself.

func RevocationTime

func RevocationTime(epoch string) (time.Time, bool)

RevocationTime returns when a revocation epoch was created and whether the epoch came from a revocation at all; the zero time reports a revocation whose time cannot be read.

func Revoke

func Revoke(ctx context.Context, client Store, userID int64) error

Revoke invalidates every session issued to the user so far.

func RevokedSince

func RevokedSince(ctx context.Context, client Store, userID int64, since time.Time) (bool, error)

RevokedSince reports whether the user's sessions were revoked at or after since. A revocation epoch carries the time it was created (a UUID v7, to the millisecond), so a capability handed out before the revocation, such as a guest order's checkout token, can be refused without a second record. A revocation in the same millisecond as since, or whose time cannot be read, counts as one after since.

func Rotate

func Rotate(ctx context.Context, client Store, userID int64) (string, error)

Rotate invalidates every session issued to the user so far and returns the epoch the sessions issued from now on carry. A flow that signs the user in right after revoking, such as a password reset, pins its session to that epoch (Grant.Epoch), so a revocation racing it cannot leave the session valid.

func SessionKey

func SessionKey(sessionID string) string

SessionKey is the Redis key recording the session sessionID; it holds the user id until the session ends.

Types

type Claims

type Claims struct {
	UserID    int64
	SessionID string
	LoginType string
	// DeviceID is the device the session is bound to; 0 for a session bound
	// to no device. The caller still checks that the device is enabled and
	// belongs to the user.
	DeviceID int64
}

Claims are the claims of a live session.

func Validate

func Validate(ctx context.Context, client ValidationStore, secret, signed string) (*Claims, error)

Validate checks a session token: its signature and lifetime, that it is a session at all, that the session was not ended, the user's session epoch and, for a device session, the device's epoch.

type Deleter

type Deleter interface {
	Del(ctx context.Context, keys ...string) *redis.IntCmd
}

Deleter is the Redis surface ending a session uses.

type Grant

type Grant struct {
	UserID int64
	// LoginType records how the user signed in; "device" marks a session of
	// the device transport.
	LoginType string
	// DeviceID binds the session to a device, so revoking the device ends it;
	// 0 issues a session bound to no device.
	DeviceID int64
	// Epoch is the user's epoch the sign-in read (AcquireEpoch) before it
	// checked the credential. A revocation that lands between the check and
	// the session would otherwise be carried by the new token, so Issue
	// refuses with ErrEpochMoved once the epoch differs. Empty skips the
	// comparison.
	Epoch string
}

Grant describes a session to issue.

type Store

type Store interface {
	Get(ctx context.Context, key string) *redis.StringCmd
	Set(ctx context.Context, key string, value any, expiration time.Duration) *redis.StatusCmd
	SetNX(ctx context.Context, key string, value any, expiration time.Duration) *redis.BoolCmd
}

Store is the Redis surface issuing and revoking sessions uses; *redis.Client satisfies it.

type ValidationStore

type ValidationStore interface {
	Store
	MGet(ctx context.Context, keys ...string) *redis.SliceCmd
}

ValidationStore adds the batched read validating a session uses.

Jump to

Keyboard shortcuts

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