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

credential

package
v0.17.0 Latest Latest
Warning

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

Go to latest
Published: Oct 19, 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