Files
ResolveSpec/pkg/security/interfaces.go
Hein 0308644075 feat(auth): add authenticate callback for fallback logic
* Implement SetAuthenticateCallback in authenticators
* Update Authenticate methods to use callback on failure
2026-05-21 11:27:51 +02:00

161 lines
6.7 KiB
Go

package security
import (
"context"
"net/http"
)
// UserContext holds authenticated user information
type UserContext struct {
UserID int `json:"user_id"`
UserName string `json:"user_name"`
UserLevel int `json:"user_level"`
SessionID string `json:"session_id"`
SessionRID int64 `json:"session_rid"`
RemoteID string `json:"remote_id"`
Roles []string `json:"roles"`
Email string `json:"email"`
Claims map[string]any `json:"claims"`
Meta map[string]any `json:"meta"` // Additional metadata that can hold any JSON-serializable values
TwoFactorEnabled bool `json:"two_factor_enabled"` // Indicates if 2FA is enabled for this user
}
// LoginRequest contains credentials for login
type LoginRequest struct {
Username string `json:"username"`
Password string `json:"password"`
TwoFactorCode string `json:"two_factor_code,omitempty"` // TOTP or backup code
Claims map[string]any `json:"claims"` // Additional login data
Meta map[string]any `json:"meta"` // Additional metadata to be set on user context
}
// RegisterRequest contains information for new user registration
type RegisterRequest struct {
Username string `json:"username"`
Password string `json:"password"`
Email string `json:"email"`
UserLevel int `json:"user_level"`
Roles []string `json:"roles"`
Claims map[string]any `json:"claims"` // Additional registration data
Meta map[string]any `json:"meta"` // Additional metadata
}
// LoginResponse contains the result of a login attempt
type LoginResponse struct {
Token string `json:"token"`
RefreshToken string `json:"refresh_token"`
User *UserContext `json:"user"`
ExpiresIn int64 `json:"expires_in"` // Token expiration in seconds
Requires2FA bool `json:"requires_2fa"` // True if 2FA code is required
TwoFactorSetupData *TwoFactorSecret `json:"two_factor_setup,omitempty"` // Present when setting up 2FA
Meta map[string]any `json:"meta"` // Additional metadata to be set on user context
}
// LogoutRequest contains information for logout
type LogoutRequest struct {
Token string `json:"token"`
UserID int `json:"user_id"`
}
// PasswordResetRequest initiates a password reset for a user
type PasswordResetRequest struct {
Email string `json:"email,omitempty"`
Username string `json:"username,omitempty"`
}
// PasswordResetResponse is returned when a reset is initiated
type PasswordResetResponse struct {
// Token is the reset token to be delivered out-of-band (e.g. email).
// The stored procedure may return it for delivery or leave it empty
// if the delivery is handled entirely in the database.
Token string `json:"token"`
ExpiresIn int64 `json:"expires_in"` // seconds
}
// PasswordResetCompleteRequest completes a password reset using the token
type PasswordResetCompleteRequest struct {
Token string `json:"token"`
NewPassword string `json:"new_password"`
}
// Authenticator handles user authentication operations
type Authenticator interface {
// Login authenticates credentials and returns a token
Login(ctx context.Context, req LoginRequest) (*LoginResponse, error)
// LoginWithCookie authenticates credentials and, when cookie sessions are enabled,
// writes the session cookie to w. Implementations that do not support cookies
// should delegate to Login and ignore w.
LoginWithCookie(ctx context.Context, req LoginRequest, w http.ResponseWriter) (*LoginResponse, error)
// Logout invalidates a user's session/token
Logout(ctx context.Context, req LogoutRequest) error
// LogoutWithCookie invalidates a user's session/token and, when cookie sessions are
// enabled, clears the session cookie on w. Implementations that do not support cookies
// should delegate to Logout and ignore w.
LogoutWithCookie(ctx context.Context, req LogoutRequest, w http.ResponseWriter) error
// Authenticate extracts and validates user from HTTP request
// Returns UserContext or error if authentication fails
Authenticate(r *http.Request) (*UserContext, error)
// SetAuthenticateCallback registers a fallback called when primary authentication fails.
// If the callback returns a non-nil UserContext, that result is used instead of the error.
SetAuthenticateCallback(fn func(r *http.Request) (*UserContext, error))
}
// Registrable allows providers to support user registration
type Registrable interface {
// Register creates a new user account
Register(ctx context.Context, req RegisterRequest) (*LoginResponse, error)
}
// ColumnSecurityProvider handles column-level security (masking/hiding)
type ColumnSecurityProvider interface {
// GetColumnSecurity loads column security rules for a user and entity
GetColumnSecurity(ctx context.Context, userID int, schema, table string) ([]ColumnSecurity, error)
}
// RowSecurityProvider handles row-level security (filtering)
type RowSecurityProvider interface {
// GetRowSecurity loads row security rules for a user and entity
GetRowSecurity(ctx context.Context, userID int, schema, table string) (RowSecurity, error)
}
// SecurityProvider is the main interface combining all security concerns
type SecurityProvider interface {
Authenticator
ColumnSecurityProvider
RowSecurityProvider
}
// Optional interfaces for advanced functionality
// Refreshable allows providers to support token refresh
type Refreshable interface {
// RefreshToken exchanges a refresh token for a new access token
RefreshToken(ctx context.Context, refreshToken string) (*LoginResponse, error)
}
// Validatable allows providers to validate tokens without full authentication
type Validatable interface {
// ValidateToken checks if a token is valid without extracting full user context
ValidateToken(ctx context.Context, token string) (bool, error)
}
// Cacheable allows providers to support caching of security rules
type Cacheable interface {
// ClearCache clears cached security rules for a user/entity
ClearCache(ctx context.Context, userID int, schema, table string) error
}
// PasswordResettable allows providers to support self-service password reset
type PasswordResettable interface {
// RequestPasswordReset creates a reset token for the given email/username
RequestPasswordReset(ctx context.Context, req PasswordResetRequest) (*PasswordResetResponse, error)
// CompletePasswordReset validates the token and sets the new password
CompletePasswordReset(ctx context.Context, req PasswordResetCompleteRequest) error
}