Documentation
¶
Index ¶
- Constants
- Variables
- func NormalizeEmail(email string) (string, error)
- func ValidatePassword(password string) error
- type CookieConfig
- type CredentialStore
- type Handler
- func (h *Handler) Login(ctx context.Context, req *connect.Request[authv1.LoginRequest]) (*connect.Response[authv1.LoginResponse], error)
- func (h *Handler) Logout(ctx context.Context, req *connect.Request[authv1.LogoutRequest]) (*connect.Response[authv1.LogoutResponse], error)
- func (h *Handler) Refresh(ctx context.Context, req *connect.Request[authv1.RefreshRequest]) (*connect.Response[authv1.RefreshResponse], error)
- func (h *Handler) Register(ctx context.Context, req *connect.Request[authv1.RegisterRequest]) (*connect.Response[authv1.RegisterResponse], error)
- func (h *Handler) Verify(ctx context.Context, req *connect.Request[authv1.VerifyRequest]) (*connect.Response[authv1.VerifyResponse], error)
- type HandlerOption
- type LoginResult
- type Provider
- type RegisterResult
- type Service
- func (s *Service) JWKS() *jose.JSONWebKeySet
- func (s *Service) Login(ctx context.Context, email, password string) (*LoginResult, error)
- func (s *Service) Logout(ctx context.Context, refreshToken string) error
- func (s *Service) Refresh(ctx context.Context, refreshToken string) (*entity.TokenPair, error)
- func (s *Service) Register(ctx context.Context, email, password string) (*RegisterResult, error)
- func (s *Service) Verify(ctx context.Context, accessToken string) (*entity.Claims, error)
- type TokenIssuer
- type TokenReuseError
- type TokenStore
- type UserStore
Constants ¶
const ( // Cookie names AccessTokenCookie = "psina_access" RefreshTokenCookie = "psina_refresh" )
const ( MinPasswordLength = 8 MaxPasswordLength = 128 )
Password constraints
Variables ¶
var ( ErrUserNotFound = errors.New("user not found") ErrInvalidCredentials = errors.New("invalid credentials") ErrUserExists = errors.New("user already exists") ErrTokenRevoked = errors.New("refresh token revoked") ErrTokenExpired = errors.New("refresh token expired") ErrTokenReuse = errors.New("refresh token reuse detected") )
Service errors.
var ErrInvalidEmail = errors.New("invalid email format")
ErrInvalidEmail is returned when email format is invalid.
var ErrPasswordTooLong = errors.New("password must be at most 128 characters")
ErrPasswordTooLong is returned when password is longer than MaxPasswordLength.
var ErrPasswordTooShort = errors.New("password must be at least 8 characters")
ErrPasswordTooShort is returned when password is shorter than MinPasswordLength.
Functions ¶
func NormalizeEmail ¶
NormalizeEmail normalizes and validates email address. Applies: trim whitespace, lowercase. Validates: contains @ and ., minimum length.
func ValidatePassword ¶
ValidatePassword checks password meets requirements. OWASP/NIST: length matters, complexity doesn't.
Types ¶
type CookieConfig ¶
type CookieConfig struct {
Enabled bool
Domain string
Path string
Secure bool
SameSite http.SameSite
}
CookieConfig holds cookie-related settings.
type CredentialStore ¶
type CredentialStore interface {
// SavePasswordHash stores a password hash for a user.
SavePasswordHash(ctx context.Context, userID, hash string) error
// GetPasswordHash retrieves a password hash for a user.
GetPasswordHash(ctx context.Context, userID string) (string, error)
}
CredentialStore handles password hash persistence for local auth. This is separated from UserStore to maintain clean architecture.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler implements Connect RPC AuthServiceHandler.
func NewHandler ¶
func NewHandler(service *Service, opts ...HandlerOption) *Handler
NewHandler creates a new RPC handler.
func (*Handler) Login ¶
func (h *Handler) Login( ctx context.Context, req *connect.Request[authv1.LoginRequest], ) (*connect.Response[authv1.LoginResponse], error)
Login authenticates a user.
func (*Handler) Logout ¶
func (h *Handler) Logout( ctx context.Context, req *connect.Request[authv1.LogoutRequest], ) (*connect.Response[authv1.LogoutResponse], error)
Logout revokes a refresh token.
func (*Handler) Refresh ¶
func (h *Handler) Refresh( ctx context.Context, req *connect.Request[authv1.RefreshRequest], ) (*connect.Response[authv1.RefreshResponse], error)
Refresh exchanges a refresh token for new tokens.
type HandlerOption ¶
type HandlerOption func(*Handler)
HandlerOption configures the Handler.
func WithCookieConfig ¶
func WithCookieConfig(config *CookieConfig) HandlerOption
WithCookieConfig sets cookie configuration.
type LoginResult ¶
LoginResult contains login result.
type Provider ¶
type Provider interface {
// Type returns the provider type identifier.
Type() string
// Authenticate verifies credentials and returns an authenticated identity.
Authenticate(ctx context.Context, req *entity.AuthRequest) (*entity.Identity, error)
// Register creates a new user account and returns the identity.
Register(ctx context.Context, req *entity.RegisterRequest) (*entity.Identity, error)
}
Provider authenticates users via a specific method (local, passkey, wallet, etc.).
type RegisterResult ¶
RegisterResult contains registration result.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service orchestrates authentication operations.
func NewService ¶
func NewService( provider Provider, tokenStore TokenStore, userStore UserStore, issuer TokenIssuer, ) *Service
NewService creates a new authentication service.
func (*Service) JWKS ¶
func (s *Service) JWKS() *jose.JSONWebKeySet
JWKS returns the JSON Web Key Set for public key verification.
type TokenIssuer ¶
type TokenIssuer interface {
// GenerateTokens creates access and refresh tokens.
// Returns: TokenPair, refresh token hash (for storage), error.
GenerateTokens(userID, email string) (*entity.TokenPair, string, error)
// ParseToken validates an access token and returns claims.
ParseToken(accessToken string) (*entity.Claims, error)
// JWKS returns the JSON Web Key Set for public key verification.
JWKS() *jose.JSONWebKeySet
}
TokenIssuer handles JWT token operations.
type TokenReuseError ¶
type TokenReuseError struct {
UserID string
}
TokenReuseError contains user context for security logging.
func (*TokenReuseError) Error ¶
func (e *TokenReuseError) Error() string
func (*TokenReuseError) Is ¶
func (e *TokenReuseError) Is(target error) bool
type TokenStore ¶
type TokenStore interface {
// SaveRefreshToken persists a refresh token.
SaveRefreshToken(ctx context.Context, token *entity.RefreshToken) error
// GetRefreshToken retrieves a refresh token by its hash.
GetRefreshToken(ctx context.Context, hash string) (*entity.RefreshToken, error)
// RevokeTokens revokes a token and all tokens in its family.
// Works for both single token revocation and family revocation.
// Query: WHERE hash = $1 OR parent = $1
RevokeTokens(ctx context.Context, hash string) error
}
TokenStore handles refresh token persistence.
type UserStore ¶
type UserStore interface {
// Create persists a new user.
Create(ctx context.Context, user *entity.User) error
// GetByID retrieves a user by ID.
GetByID(ctx context.Context, id string) (*entity.User, error)
// GetByEmail retrieves a user by email address.
GetByEmail(ctx context.Context, email string) (*entity.User, error)
// Delete removes a user by ID.
Delete(ctx context.Context, id string) error
}
UserStore handles user persistence.