multisession

package
v1.3.0 Latest Latest
Warning

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

Go to latest
Published: Oct 23, 2026 License: MIT, MIT Imports: 13 Imported by: 0

README

GoModularAuth MultiSession Plugin

gomodularauth-multi-session provides advanced management of multiple concurrent Core Sessions for GoModularAuth users while strictly preserving Core session semantics.

Installation

go get github.com/BladiCreator/go-modular-auth/plugins/multisession

Quick Start

package main

import (
	"context"
	"fmt"
	"log"

	auth "github.com/BladiCreator/go-modular-auth"
	adaptermem "github.com/BladiCreator/go-modular-auth/adapters/memory"
	multisession "github.com/BladiCreator/go-modular-auth/plugins/multisession"
	"github.com/BladiCreator/go-modular-auth/plugins/multisession/plugins"
)

func main() {
	ctx := context.Background()

	// 1. Initialize GoModularAuth with MultiSession plugin
	app, err := auth.New(auth.Config{
		Adapter: adaptermem.NewAdapter(),
		Cache:   adaptermem.NewCache(),
		Plugins: []auth.PluginModule{
			multisession.New(
				multisession.WithMaxConcurrentSessions(5, multisession.OverflowRevokeOldest),
			),
		},
	})
	if err != nil {
		log.Fatalf("failed to initialize auth: %v", err)
	}

	// 2. Retrieve the typed MultiSession capability
	sessionMgr, err := auth.Get[plugins.MultiSession](app)
	if err != nil {
		log.Fatalf("failed to resolve capability: %v", err)
	}

	// 3. User signs in, producing sessions
	up, err := app.SignUp(ctx, auth.SignUpInput{
		Email:    "alice@example.com",
		Password: "SuperSecurePassword123!",
		Session: auth.SessionOptions{
			IPAddress: "192.168.1.100",
			UserAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/120.0.0.0",
		},
	})
	if err != nil {
		log.Fatalf("signup failed: %v", err)
	}

	// 4. List user's active sessions with rich device metadata
	sessions, err := sessionMgr.ListDetailedSessions(ctx, up.User.ID, up.Session.ID)
	if err != nil {
		log.Fatalf("list sessions failed: %v", err)
	}

	for _, s := range sessions {
		fmt.Printf("Session ID: %s | Device: %s (%s) | Current: %t\n",
			s.Session.ID, s.Metadata.Device.Name, s.Metadata.Device.OS, s.IsCurrent)
	}

	// 5. Revoke other sessions (e.g. "Log out of all other devices")
	if err := sessionMgr.RevokeOtherSessions(ctx, up.User.ID, up.Session.ID); err != nil {
		log.Fatalf("failed to revoke other sessions: %v", err)
	}
}

Detailed guide: doc/plugins/multisession.md.

Documentation

Overview

Package multisession enriches Core sessions with device metadata, user-agent parsing, and multi-device session management and remote revocation.

Index

Constants

View Source
const (
	EventSessionRevoked  auth.EventName = "multisession.session_revoked"
	EventSessionsRevoked auth.EventName = "multisession.sessions_revoked"
	EventSessionEvicted  auth.EventName = "multisession.session_evicted"
	EventMetadataUpdated auth.EventName = "multisession.metadata_updated"
)

Event names emitted by the multisession module.

View Source
const (
	ModelSessionMetadata = "session_metadata"
)
View Source
const PluginID = "multisession"

PluginID identifies this plugin in the GoModularAuth runtime.

Variables

View Source
var (
	// ErrSessionNotFound is returned when the target session does not exist.
	ErrSessionNotFound = errors.New("multisession: session not found")

	// ErrSessionAlreadyRevoked is returned when operating on an already revoked session.
	ErrSessionAlreadyRevoked = errors.New("multisession: session already revoked")

	// ErrInvalidInput is returned when required parameters (e.g., userID, sessionID) are empty or malformed.
	ErrInvalidInput = errors.New("multisession: invalid input")

	// ErrUnauthorized is returned when a session does not belong to the specified user.
	ErrUnauthorized = errors.New("multisession: unauthorized session access")

	// ErrMaxConcurrentSessionsReached is returned when a new session cannot be created
	// because the user reached the configured maximum allowed concurrent sessions and
	// the overflow policy is set to OverflowReject.
	ErrMaxConcurrentSessionsReached = errors.New("multisession: maximum concurrent sessions reached")

	// ErrMetadataNotFound is returned when no metadata is stored for the requested session.
	ErrMetadataNotFound = errors.New("multisession: session metadata not found")
)

Functions

func RegisterSchema added in v1.3.0

func RegisterSchema(s *schema.Schema) error

RegisterSchema registers the session_metadata model with the unified schema.

Types

type Capability added in v1.3.0

type Capability = MultiSession

Capability is an alias for MultiSession to support standard capability discovery conventions.

type Config

type Config struct {
	// MaxConcurrentSessions sets the maximum concurrent active sessions per user.
	// 0 or negative value disables concurrency limiting.
	MaxConcurrentSessions int

	// OverflowPolicy controls what happens when the session concurrency limit is exceeded.
	OverflowPolicy OverflowPolicy

	// MetadataCacheTTL controls how long session metadata is cached.
	MetadataCacheTTL time.Duration
}

Config holds configuration parameters for the multisession plugin.

type DeviceMetadata added in v1.3.0

type DeviceMetadata struct {
	Name      string `json:"name,omitempty"`
	Type      string `json:"type,omitempty"`
	OS        string `json:"os,omitempty"`
	Browser   string `json:"browser,omitempty"`
	IPAddress string `json:"ip_address,omitempty"`
}

DeviceMetadata contains optional device identification information.

func ParseUserAgent added in v1.3.0

func ParseUserAgent(ua, ip string) DeviceMetadata

ParseUserAgent extracts basic device metadata from a User-Agent string and IP address using pure Go string matching without external dependencies.

type DeviceRecord added in v1.3.0

type DeviceRecord struct {
	Name      string `json:"name,omitempty"`
	Type      string `json:"type,omitempty"`
	OS        string `json:"os,omitempty"`
	Browser   string `json:"browser,omitempty"`
	IPAddress string `json:"ip_address,omitempty"`
}

DeviceRecord contains persistent device identification details.

type Metadata added in v1.3.0

type Metadata struct {
	SessionID string            `json:"session_id"`
	UserID    string            `json:"user_id"`
	Device    DeviceMetadata    `json:"device"`
	Custom    map[string]string `json:"custom,omitempty"`
	CreatedAt time.Time         `json:"created_at"`
	UpdatedAt time.Time         `json:"updated_at"`
}

Metadata represents optional session and device metadata associated with a Core Session.

type MetadataInput added in v1.3.0

type MetadataInput struct {
	Device DeviceMetadata    `json:"device"`
	Custom map[string]string `json:"custom,omitempty"`
}

MetadataInput defines parameters for setting or updating session metadata.

type MetadataRecord added in v1.3.0

type MetadataRecord struct {
	SessionID string            `json:"session_id"`
	UserID    string            `json:"user_id"`
	Device    DeviceRecord      `json:"device"`
	Custom    map[string]string `json:"custom,omitempty"`
	CreatedAt time.Time         `json:"created_at"`
	UpdatedAt time.Time         `json:"updated_at"`
}

MetadataRecord is the persistent representation of session metadata.

type MetadataUpdatedPayload added in v1.3.0

type MetadataUpdatedPayload struct {
	SessionID string    `json:"session_id"`
	UserID    string    `json:"user_id"`
	UpdatedAt time.Time `json:"updated_at"`
}

MetadataUpdatedPayload represents observational data when session metadata is set or changed.

type Module added in v1.3.0

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

Module implements auth.PluginModule using plugin-sdk.

func New

func New(opts ...Option) *Module

New creates an installable multisession PluginModule with optional configurations.

func (*Module) ID added in v1.3.0

func (m *Module) ID() string

ID returns the module's unique identifier.

func (*Module) Init added in v1.3.0

func (m *Module) Init(h *auth.Host) error

Init configures infrastructure, registers hooks, and provides the typed Capability into GoModularAuth via plugin-sdk.

func (*Module) RegisterSchema added in v1.3.0

func (m *Module) RegisterSchema(s *schema.Schema) error

RegisterSchema registers the plugin's models into the schema.

type MultiSession added in v1.3.0

type MultiSession interface {
	// ListSessions returns all active, valid sessions for a user from Core SessionStore.
	ListSessions(ctx context.Context, userID string) ([]*session.Session, error)

	// ListDetailedSessions returns all active sessions for a user, enriched with device
	// and custom metadata, and flags the current session if currentSessionID matches.
	ListDetailedSessions(ctx context.Context, userID string, currentSessionID string) ([]*SessionDetail, error)

	// GetSession returns an active session by its ID. Returns ErrSessionNotFound if not found or expired.
	GetSession(ctx context.Context, sessionID string) (*session.Session, error)

	// GetDetailedSession returns an active session enriched with its metadata.
	GetDetailedSession(ctx context.Context, sessionID string) (*SessionDetail, error)

	// RevokeSession revokes a specific session by ID, updating the Store first,
	// invalidating relevant Cache entries, and publishing revocation events.
	RevokeSession(ctx context.Context, sessionID string) error

	// RevokeOtherSessions revokes all active sessions for userID except currentSessionID.
	RevokeOtherSessions(ctx context.Context, userID, currentSessionID string) error

	// RevokeAllSessions revokes every active session for userID.
	RevokeAllSessions(ctx context.Context, userID string) error

	// SetMetadata persists or updates device and custom metadata for a session.
	SetMetadata(ctx context.Context, sessionID string, meta MetadataInput) error

	// GetMetadata retrieves metadata associated with a session.
	GetMetadata(ctx context.Context, sessionID string) (*Metadata, error)
}

MultiSession is the strongly typed capability provided by the multisession module.

type Option

type Option func(*Config)

Option configures the multisession plugin.

func WithMaxConcurrentSessions added in v1.3.0

func WithMaxConcurrentSessions(limit int, policy ...OverflowPolicy) Option

WithMaxConcurrentSessions configures the concurrent session limit and optional overflow policy.

func WithMetadataCacheTTL added in v1.3.0

func WithMetadataCacheTTL(ttl time.Duration) Option

WithMetadataCacheTTL sets the cache duration for session metadata.

func WithOverflowPolicy added in v1.3.0

func WithOverflowPolicy(policy OverflowPolicy) Option

WithOverflowPolicy sets the strategy when MaxConcurrentSessions is exceeded.

type OverflowPolicy added in v1.3.0

type OverflowPolicy string

OverflowPolicy defines the action taken when a user exceeds MaxConcurrentSessions.

const (
	// OverflowRevokeOldest automatically revokes the user's oldest active session(s)
	// to make room for the newly requested session (FIFO eviction).
	OverflowRevokeOldest OverflowPolicy = "revoke_oldest"

	// OverflowReject rejects the new session creation request by returning
	// ErrMaxConcurrentSessionsReached.
	OverflowReject OverflowPolicy = "reject"
)

type SessionDetail added in v1.3.0

type SessionDetail struct {
	Session   *session.Session `json:"session"`
	Metadata  *Metadata        `json:"metadata,omitempty"`
	IsCurrent bool             `json:"is_current"`
}

SessionDetail represents a Core session enriched with optional metadata and current status flag. Crucially, it reuses the Core session.Session entity and does not replace it.

type SessionEvictedPayload added in v1.3.0

type SessionEvictedPayload struct {
	SessionID string    `json:"session_id"`
	UserID    string    `json:"user_id"`
	EvictedAt time.Time `json:"evicted_at"`
	Reason    string    `json:"reason"`
}

SessionEvictedPayload represents observational data when a session is evicted due to concurrency limits.

type SessionRevokedPayload added in v1.3.0

type SessionRevokedPayload struct {
	SessionID string    `json:"session_id"`
	UserID    string    `json:"user_id"`
	RevokedAt time.Time `json:"revoked_at"`
	Reason    string    `json:"reason,omitempty"`
}

SessionRevokedPayload represents observational data when a single session is revoked.

type SessionsRevokedPayload added in v1.3.0

type SessionsRevokedPayload struct {
	UserID          string    `json:"user_id"`
	RevokedCount    int       `json:"revoked_count"`
	ExceptSessionID string    `json:"except_session_id,omitempty"`
	RevokedAt       time.Time `json:"revoked_at"`
	Reason          string    `json:"reason,omitempty"`
}

SessionsRevokedPayload represents observational data when bulk sessions are revoked.

Directories

Path Synopsis
Package plugins exposes the capability aliases for GoModularAuth plugins.
Package plugins exposes the capability aliases for GoModularAuth plugins.

Jump to

Keyboard shortcuts

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