credential

package
v0.14.0 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package credential provides credential management for principals. Credentials can be passwords, API keys, keypairs, WebAuthn credentials, TOTP secrets, client secrets, or login tokens.

Index

Constants

View Source
const (
	// LoginTokenPrefix starts every login token. Tokens use only uppercase
	// letters and digits so a QR code can encode them in alphanumeric mode.
	LoginTokenPrefix = "SFLT"
	// LoginTokenBytes is the number of random bytes in a login token.
	LoginTokenBytes = 32

	// DefaultLoginTokenTTL is the platform default lifetime of a reusable
	// login token.
	DefaultLoginTokenTTL = 30 * 24 * time.Hour
	// DefaultLoginTokenMaxTTL is the platform ceiling on any login token's
	// lifetime: one school year plus slack.
	DefaultLoginTokenMaxTTL = 400 * 24 * time.Hour
	// DefaultSingleUseLoginTokenTTL is the default lifetime of a
	// single-use login token.
	DefaultSingleUseLoginTokenTTL = 20 * time.Minute
)
View Source
const (
	// APIKeyPrefix is the prefix for generated API keys.
	APIKeyPrefix = "sf_"
	// APIKeyBytes is the number of random bytes for API key generation.
	APIKeyBytes = 32
)

Variables

View Source
var (
	// ErrInvalidLoginToken is returned for every login token that cannot
	// be used: unknown, malformed, expired, revoked, inactive, or already
	// used. Callers must not distinguish these cases to the presenter.
	ErrInvalidLoginToken = errors.New("credential: invalid login token")
	// ErrInvalidExpiry is returned when a requested expiry is not in the
	// future.
	ErrInvalidExpiry = errors.New("credential: login token expiry must be in the future")
)
View Source
var ErrCorruptCredential = errors.New("credential: stored credential is corrupt")

ErrCorruptCredential is returned when a stored credential cannot be read, such as a secret hash in an unknown format.

View Source
var ErrInvalidClientCredentials = errors.New("credential: invalid client credentials")

ErrInvalidClientCredentials is returned by ValidateClientSecret for an unknown client, a client with no usable secret, and a wrong secret alike, so a caller cannot learn which client IDs exist.

Functions

func LoginTokenIssuedBy added in v0.14.0

func LoginTokenIssuedBy(c *Credential) (uuid.UUID, error)

LoginTokenIssuedBy returns the manager that issued a login token, or uuid.Nil when none is recorded.

func LoginTokenSingleUse added in v0.14.0

func LoginTokenSingleUse(c *Credential) bool

LoginTokenSingleUse reports whether a login token is single-use.

Types

type CreateAPIKeyInput

type CreateAPIKeyInput struct {
	PrincipalID uuid.UUID
	Name        string
	Scopes      []string
	ExpiresAt   *time.Time
	Metadata    map[string]any
}

CreateAPIKeyInput contains fields for creating an API key credential.

type CreateClientSecretInput

type CreateClientSecretInput struct {
	PrincipalID uuid.UUID
	Name        string
	ExpiresAt   *time.Time
	Metadata    map[string]any
}

CreateClientSecretInput contains fields for creating a client secret.

type CreateKeypairInput

type CreateKeypairInput struct {
	PrincipalID  uuid.UUID
	Name         string
	KeyAlgorithm string // RS256, ES256, EdDSA
	PublicKeyPEM string
	Scopes       []string
	ExpiresAt    *time.Time
	Metadata     map[string]any
}

CreateKeypairInput contains fields for creating a keypair credential.

type CreatePasswordInput

type CreatePasswordInput struct {
	PrincipalID uuid.UUID
	Password    string `json:"-"` //nolint:gosec // G117: field holds user-provided value, not a hardcoded secret
}

CreatePasswordInput contains fields for creating a password credential.

type Credential

type Credential struct {
	ID            uuid.UUID      `json:"id"`
	PrincipalID   uuid.UUID      `json:"principal_id"`
	Type          Type           `json:"type"`
	Identifier    string         `json:"identifier,omitempty"` // e.g., key prefix for API keys
	Name          string         `json:"name,omitempty"`
	Scopes        []string       `json:"scopes,omitempty"`
	Active        bool           `json:"active"`
	ExpiresAt     *time.Time     `json:"expires_at,omitempty"`
	Revoked       bool           `json:"revoked"`
	RevokedAt     *time.Time     `json:"revoked_at,omitempty"`
	RevokedReason string         `json:"revoked_reason,omitempty"`
	LastUsedAt    *time.Time     `json:"last_used_at,omitempty"`
	LastUsedIP    string         `json:"last_used_ip,omitempty"`
	Metadata      map[string]any `json:"metadata,omitempty"`
	CreatedAt     time.Time      `json:"created_at"`
	UpdatedAt     time.Time      `json:"updated_at"`
}

Credential represents a credential record.

type DefaultService

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

DefaultService implements the Service interface.

func (*DefaultService) CreateAPIKey

func (s *DefaultService) CreateAPIKey(ctx context.Context, input CreateAPIKeyInput) (*GeneratedAPIKey, error)

CreateAPIKey generates a new API key for a principal.

func (*DefaultService) CreateClientSecret

func (s *DefaultService) CreateClientSecret(ctx context.Context, input CreateClientSecretInput) (*GeneratedClientSecret, error)

CreateClientSecret generates a new client secret for an application principal.

func (*DefaultService) CreateKeypair

func (s *DefaultService) CreateKeypair(ctx context.Context, input CreateKeypairInput) (*KeypairCredential, error)

CreateKeypair creates a keypair credential for a principal.

func (*DefaultService) CreatePassword

func (s *DefaultService) CreatePassword(ctx context.Context, input CreatePasswordInput) error

CreatePassword creates a password credential for a principal.

func (*DefaultService) GetByID

func (s *DefaultService) GetByID(ctx context.Context, id uuid.UUID) (*Credential, error)

GetByID retrieves a credential by ID.

func (*DefaultService) GetKeypairByKeyID

func (s *DefaultService) GetKeypairByKeyID(ctx context.Context, keyID string) (*KeypairCredential, error)

GetKeypairByKeyID retrieves a keypair credential by key ID.

func (*DefaultService) IssueLoginToken added in v0.14.0

func (s *DefaultService) IssueLoginToken(ctx context.Context, input IssueLoginTokenInput) (*GeneratedLoginToken, error)

IssueLoginToken creates a login token credential and returns its plain value once.

func (*DefaultService) ListAPIKeys

func (s *DefaultService) ListAPIKeys(ctx context.Context, principalID uuid.UUID) ([]*Credential, error)

ListAPIKeys lists all API keys for a principal.

func (*DefaultService) ListKeypairs

func (s *DefaultService) ListKeypairs(ctx context.Context, principalID uuid.UUID) ([]*KeypairCredential, error)

ListKeypairs lists all keypairs for a principal.

func (*DefaultService) Revoke

func (s *DefaultService) Revoke(ctx context.Context, id uuid.UUID, reason string) error

Revoke revokes a credential.

func (*DefaultService) UpdateLastUsed

func (s *DefaultService) UpdateLastUsed(ctx context.Context, id uuid.UUID, ip string) error

UpdateLastUsed updates the last used timestamp and IP.

func (*DefaultService) UpdatePassword

func (s *DefaultService) UpdatePassword(ctx context.Context, principalID uuid.UUID, newPassword string) error

UpdatePassword updates the password for a principal.

func (*DefaultService) ValidateAPIKey

func (s *DefaultService) ValidateAPIKey(ctx context.Context, plainKey string) (*Credential, error)

ValidateAPIKey validates an API key and returns the associated credential.

func (*DefaultService) ValidateClientSecret

func (s *DefaultService) ValidateClientSecret(ctx context.Context, clientID, plainSecret string) (*Credential, error)

ValidateClientSecret validates a client secret.

func (*DefaultService) VerifyLoginToken added in v0.14.0

func (s *DefaultService) VerifyLoginToken(ctx context.Context, plainToken, ip string) (*Credential, error)

VerifyLoginToken returns the credential for a usable login token and records its use. A single-use token is revoked atomically, so it succeeds at most once even under concurrent presentation. Every unusable token yields ErrInvalidLoginToken.

func (*DefaultService) VerifyPassword

func (s *DefaultService) VerifyPassword(ctx context.Context, principalID uuid.UUID, password string) (bool, error)

VerifyPassword verifies a password against the stored hash.

type GeneratedAPIKey

type GeneratedAPIKey struct {
	Credential *Credential `json:"credential"`
	PlainKey   string      `json:"plain_key"` // Only available at creation time
	Prefix     string      `json:"prefix"`    // First 8 chars for identification
}

GeneratedAPIKey contains a newly generated API key. The PlainKey is only available at creation time.

type GeneratedClientSecret

type GeneratedClientSecret struct {
	Credential  *Credential `json:"credential"`
	PlainSecret string      `json:"plain_secret"` // Only available at creation time
	Prefix      string      `json:"prefix"`       // First 8 chars for identification
}

GeneratedClientSecret contains a newly generated client secret.

type GeneratedLoginToken added in v0.14.0

type GeneratedLoginToken struct {
	Credential *Credential `json:"credential"`
	PlainToken string      `json:"plain_token"`
	Prefix     string      `json:"prefix"`
}

GeneratedLoginToken is a newly issued login token. PlainToken is available only here; the database stores its hash.

type IssueLoginTokenInput added in v0.14.0

type IssueLoginTokenInput struct {
	// PrincipalID is the managed principal the token signs in.
	PrincipalID uuid.UUID
	// IssuedBy is the manager issuing the token.
	IssuedBy uuid.UUID
	// ExpiresAt is required; resolve it with LoginTokenPolicy.ExpiresAt.
	ExpiresAt time.Time
	// SingleUse revokes the token on its first successful use.
	SingleUse bool
	// Name is an optional label, such as the device or card it is for.
	Name string
}

IssueLoginTokenInput describes a login token to issue.

type KeypairCredential

type KeypairCredential struct {
	Credential   *Credential `json:"credential"`
	KeyID        string      `json:"key_id"`        // Used in JWT kid header
	KeyAlgorithm string      `json:"key_algorithm"` // RS256, ES256, etc.
	PublicKeyPEM string      `json:"public_key_pem"`
}

KeypairCredential contains keypair-specific data.

type LoginTokenPolicy added in v0.14.0

type LoginTokenPolicy struct {
	// DefaultTTL applies to reusable tokens issued without an explicit
	// expiry. A client may set its own, for example a school year.
	DefaultTTL time.Duration
	// MaxTTL caps every token's lifetime.
	MaxTTL time.Duration
	// SingleUseTTL applies to single-use tokens issued without an
	// explicit expiry.
	SingleUseTTL time.Duration
}

LoginTokenPolicy bounds login token lifetimes. Zero fields use the platform defaults.

func (LoginTokenPolicy) ExpiresAt added in v0.14.0

func (p LoginTokenPolicy) ExpiresAt(now time.Time, requested *time.Time, singleUse bool) (exp time.Time, clamped bool, err error)

ExpiresAt resolves a token's expiry: the requested time if given, else the single-use or default lifetime, never beyond MaxTTL. clamped reports that the result was cut to MaxTTL, which callers should log.

type Service

type Service interface {
	// Password operations
	CreatePassword(ctx context.Context, input CreatePasswordInput) error
	VerifyPassword(ctx context.Context, principalID uuid.UUID, password string) (bool, error)
	UpdatePassword(ctx context.Context, principalID uuid.UUID, newPassword string) error

	// API key operations
	CreateAPIKey(ctx context.Context, input CreateAPIKeyInput) (*GeneratedAPIKey, error)
	ValidateAPIKey(ctx context.Context, plainKey string) (*Credential, error)
	ListAPIKeys(ctx context.Context, principalID uuid.UUID) ([]*Credential, error)

	// Client secret operations
	CreateClientSecret(ctx context.Context, input CreateClientSecretInput) (*GeneratedClientSecret, error)
	ValidateClientSecret(ctx context.Context, clientID, plainSecret string) (*Credential, error)

	// Keypair operations
	CreateKeypair(ctx context.Context, input CreateKeypairInput) (*KeypairCredential, error)
	GetKeypairByKeyID(ctx context.Context, keyID string) (*KeypairCredential, error)
	ListKeypairs(ctx context.Context, principalID uuid.UUID) ([]*KeypairCredential, error)

	// Login token operations
	IssueLoginToken(ctx context.Context, input IssueLoginTokenInput) (*GeneratedLoginToken, error)
	VerifyLoginToken(ctx context.Context, plainToken, ip string) (*Credential, error)

	// Common operations
	GetByID(ctx context.Context, id uuid.UUID) (*Credential, error)
	Revoke(ctx context.Context, id uuid.UUID, reason string) error
	UpdateLastUsed(ctx context.Context, id uuid.UUID, ip string) error
}

Service defines the business logic interface for credentials.

func NewService

func NewService(client *ent.Client) Service

NewService creates a new CredentialService.

type Type

type Type string

Type represents the type of credential.

const (
	// TypePassword represents a password credential.
	TypePassword Type = "password"
	// TypeAPIKey represents an API key credential.
	TypeAPIKey Type = "api_key"
	// TypeKeypair represents a public/private keypair credential.
	TypeKeypair Type = "keypair"
	// TypeWebAuthn represents a WebAuthn credential.
	TypeWebAuthn Type = "webauthn"
	// TypeTOTP represents a TOTP credential.
	TypeTOTP Type = "totp"
	// TypeClientSecret represents an OAuth client secret.
	TypeClientSecret Type = "client_secret"
	// TypeLoginToken represents a manager-issued sign-in token for a
	// managed principal.
	TypeLoginToken Type = "login_token"
)

Jump to

Keyboard shortcuts

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