Documentation
¶
Overview ¶
Package superuser implements a system-operator identity plane that is structurally separate from the user package: its own table (via SuperuserStore), its own claims type, and — critically — its own JWT audience, so a perfectly valid user access token can never be accepted by superuser middleware, and vice versa, even though both planes may share the same underlying jwt.Signer/secret.
Index ¶
- Constants
- Variables
- type Claims
- type Config
- type Service
- func (s *Service) Authenticate(ctx context.Context, email, password, userAgent, ipAddress string) (TokenPair, error)
- func (s *Service) Bootstrap(ctx context.Context, email, password, displayName string) (store.Superuser, error)
- func (s *Service) CreateSuperuser(ctx context.Context, email, password, displayName, createdByID string) (store.Superuser, error)
- func (s *Service) Deactivate(ctx context.Context, callerID, targetID string) error
- func (s *Service) Impersonate(ctx context.Context, superuserID, targetUserID, targetUserEmail string) (string, error)
- func (s *Service) ListSuperusers(ctx context.Context) ([]store.Superuser, error)
- func (s *Service) Logout(ctx context.Context, refreshToken string) error
- func (s *Service) Refresh(ctx context.Context, refreshToken, userAgent, ipAddress string) (TokenPair, error)
- func (s *Service) Verify(token string) (Claims, error)
- type Stores
- type TokenPair
Constants ¶
const DefaultAudience = "authit-superuser"
DefaultAudience is the JWT audience claim that marks a token as belonging to the superuser plane.
Variables ¶
var ( ErrInvalidCredentials = errors.New("authit/superuser: invalid credentials") ErrAccountLocked = errors.New("authit/superuser: account locked") ErrInactive = errors.New("authit/superuser: account is not active") ErrInvalidToken = errors.New("authit/superuser: invalid or expired token") ErrCannotDeactivateSelf = errors.New("authit/superuser: cannot deactivate your own account") ErrAlreadyBootstrapped = errors.New("authit/superuser: at least one superuser already exists") )
Functions ¶
This section is empty.
Types ¶
type Claims ¶
type Claims struct {
jwt.RegisteredClaims
Email string `json:"email,omitempty"`
}
Claims is the admin-plane access token claim set. Subject carries the superuser ID. Impersonation does NOT use this type — Impersonate mints an ordinary jwt.Claims (user-plane) token instead, so it flows through existing user routes unchanged; see jwt.Claims.ActorID.
func (Claims) HasAudience ¶
HasAudience reports whether aud is present in the claims' audience list.
type Config ¶
type Config struct {
// Audience is the JWT audience claim that marks a token as belonging to
// this plane. Defaults to DefaultAudience.
Audience string
// AccessTokenTTL defaults to 5 minutes.
AccessTokenTTL time.Duration
// RefreshTokenTTL defaults to 7 days.
RefreshTokenTTL time.Duration
// ImpersonationTTL defaults to 15 minutes.
ImpersonationTTL time.Duration
// MaxFailedLoginAttempts defaults to 5. Ignored if Stores.Lockouts is
// nil.
MaxFailedLoginAttempts int
// FailedLoginWindow defaults to 15 minutes.
FailedLoginWindow time.Duration
// AuditLogger receives security-relevant events (login, lockout,
// deactivation, impersonation). Nil means events are not recorded —
// see package audit.
AuditLogger audit.Logger
}
Config tunes the superuser package's flows. Defaults are intentionally stricter than the user package's: short-lived access tokens, since operator sessions warrant more frequent re-authentication.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service implements the superuser/operator auth plane.
func NewService ¶
NewService constructs a Service. signer may be the same jwt.Signer used by the user package — audience separation, not a separate secret, is what keeps the two planes from accepting each other's tokens. Config.AuditLogger may be nil, in which case audit.NoopLogger is used.
func (*Service) Authenticate ¶
func (s *Service) Authenticate(ctx context.Context, email, password, userAgent, ipAddress string) (TokenPair, error)
Authenticate verifies email/password against the superuser table and issues a token pair scoped to this plane's audience.
func (*Service) Bootstrap ¶
func (s *Service) Bootstrap(ctx context.Context, email, password, displayName string) (store.Superuser, error)
Bootstrap creates the first superuser, and only the first: it fails with ErrAlreadyBootstrapped if any superuser already exists. Intended to be called once at application startup from a trusted source (e.g. an environment variable), never from an HTTP handler.
func (*Service) CreateSuperuser ¶
func (s *Service) CreateSuperuser(ctx context.Context, email, password, displayName, createdByID string) (store.Superuser, error)
CreateSuperuser creates an additional superuser, attributed to createdByID (another superuser's ID). There is no public registration endpoint for this plane by design — only an authenticated superuser (or Bootstrap) can create one.
func (*Service) Deactivate ¶
Deactivate soft-deletes a superuser account and revokes all of its sessions. There is deliberately no reactivate: a deactivated superuser is not recoverable through this API.
func (*Service) Impersonate ¶
func (s *Service) Impersonate(ctx context.Context, superuserID, targetUserID, targetUserEmail string) (string, error)
Impersonate mints a short-lived, ordinary user-plane access token (no superuser audience) for targetUserID, stamped with ActorID=superuserID so it is distinguishable from a normal login (jwt.Claims.IsImpersonation). Because it carries the user-plane's normal shape, it flows through existing user routes/middleware unchanged.
The token is not tracked server-side: it is valid until it naturally expires (Config.ImpersonationTTL, default 15 minutes) and cannot be revoked early. This bounds blast radius via a short TTL rather than a live revocation check on every request. The call is recorded through Config.AuditLogger if one is configured (see package audit) — early revocation is still on the host, but the trail is not.
func (*Service) ListSuperusers ¶
ListSuperusers lists every superuser account.
type Stores ¶
type Stores struct {
Superusers store.SuperuserStore
RefreshTokens store.SuperuserRefreshTokenStore
// Lockouts is optional; if nil, failed-login lockout is disabled.
Lockouts store.LockoutStore
}
Stores groups the persistence ports the superuser package needs.