Documentation
¶
Overview ¶
Package auth implements authentication for the Klever Node Hub dashboard.
DEPENDENCY NOTE: This package uses github.com/go-webauthn/webauthn as the sole exception to the stdlib-only rule. WebAuthn/FIDO2 requires CBOR parsing, attestation verification, and compliance with W3C WebAuthn spec — implementing this manually would be error-prone and a security risk. The go-webauthn library is the standard Go implementation, actively maintained, and widely audited. All other auth components (JWT, recovery codes, middleware) use stdlib only.
Index ¶
- Variables
- func GenerateSigningKey() ([]byte, error)
- func HashArgon2id(input string) (string, error)
- func Middleware(jm *JWTManager) func(http.Handler) http.Handler
- func VerifyArgon2id(input, storedHash string) bool
- type JWTClaims
- type JWTManager
- func (jm *JWTManager) IssueTokenPair(subject string) (*TokenPair, error)
- func (jm *JWTManager) RefreshTokenPair(refreshToken string) (*TokenPair, error)
- func (jm *JWTManager) ValidateAccessToken(token string) (*JWTClaims, error)
- func (jm *JWTManager) ValidateRefreshToken(token string) (*JWTClaims, error)
- type KleverAuthManager
- func (k *KleverAuthManager) Address() string
- func (k *KleverAuthManager) CreateChallenge(address string) (string, error)
- func (k *KleverAuthManager) CreateSetupChallenge(address string) (string, error)
- func (k *KleverAuthManager) HasAddress() bool
- func (k *KleverAuthManager) RemoveAddress()
- func (k *KleverAuthManager) SetAddress(address string) error
- func (k *KleverAuthManager) VerifySetupSignature(address, nonce, signature string) error
- func (k *KleverAuthManager) VerifySignature(address, nonce, signature string) error
- type PasskeyCredential
- type PasswordManager
- type RateLimiter
- type RecoveryCode
- type RecoveryManager
- type TokenPair
- type WebAuthnConfig
- type WebAuthnManager
- func (wm *WebAuthnManager) BeginLogin() (*protocol.CredentialAssertion, string, error)
- func (wm *WebAuthnManager) BeginRegistration(passkeyName string) (*protocol.CredentialCreation, string, error)
- func (wm *WebAuthnManager) CredentialCount() int
- func (wm *WebAuthnManager) Credentials() []PasskeyCredential
- func (wm *WebAuthnManager) DeletePasskey(id string) error
- func (wm *WebAuthnManager) FinishLogin(sessionID string, response *protocol.ParsedCredentialAssertionData) error
- func (wm *WebAuthnManager) FinishRegistration(sessionID string, response *protocol.ParsedCredentialCreationData, name string) error
- func (wm *WebAuthnManager) HasCredentials() bool
Constants ¶
This section is empty.
Variables ¶
var ( ErrNoKleverAddress = errors.New("no klever admin address configured") ErrInvalidAddress = errors.New("invalid klever address format") ErrChallengeExpired = errors.New("challenge expired or not found") ErrAddressMismatch = errors.New("address does not match registered admin") ErrInvalidSignature = errors.New("invalid signature") )
var ErrPasswordTooShort = errors.New("password must be at least 8 characters")
ErrPasswordTooShort is returned when the password is shorter than the minimum length.
Functions ¶
func GenerateSigningKey ¶
GenerateSigningKey creates a cryptographically random 32-byte signing key.
func HashArgon2id ¶
HashArgon2id hashes the input with Argon2id and returns hex(salt + hash).
func Middleware ¶
func Middleware(jm *JWTManager) func(http.Handler) http.Handler
Middleware creates an HTTP middleware that validates JWT tokens. Tokens are read from the "Authorization: Bearer <token>" header or from an httpOnly cookie named "access_token".
func VerifyArgon2id ¶
VerifyArgon2id checks an input against a stored Argon2id hash. Uses constant-time comparison to prevent timing attacks.
Types ¶
type JWTClaims ¶
type JWTClaims struct {
Subject string `json:"sub"`
IssuedAt int64 `json:"iat"`
ExpiresAt int64 `json:"exp"`
TokenType string `json:"type"` // "access" or "refresh"
}
JWTClaims holds the JWT payload.
func ClaimsFromContext ¶
ClaimsFromContext extracts JWT claims from the request context. Returns nil if no claims are present.
type JWTManager ¶
type JWTManager struct {
// contains filtered or unexported fields
}
JWTManager handles JWT token creation and validation.
func NewJWTManager ¶
func NewJWTManager(signingKey []byte) (*JWTManager, error)
NewJWTManager creates a new JWTManager with the given signing key. Key must be at least 32 bytes.
func (*JWTManager) IssueTokenPair ¶
func (jm *JWTManager) IssueTokenPair(subject string) (*TokenPair, error)
IssueTokenPair creates a new access + refresh token pair.
func (*JWTManager) RefreshTokenPair ¶
func (jm *JWTManager) RefreshTokenPair(refreshToken string) (*TokenPair, error)
RefreshTokenPair validates a refresh token and issues a new token pair.
func (*JWTManager) ValidateAccessToken ¶
func (jm *JWTManager) ValidateAccessToken(token string) (*JWTClaims, error)
ValidateAccessToken validates an access token and returns its claims.
func (*JWTManager) ValidateRefreshToken ¶
func (jm *JWTManager) ValidateRefreshToken(token string) (*JWTClaims, error)
ValidateRefreshToken validates a refresh token and returns its claims.
type KleverAuthManager ¶
type KleverAuthManager struct {
// contains filtered or unexported fields
}
KleverAuthManager handles Klever Extension wallet authentication. It stores a single admin klv1... address and manages challenge-response sessions.
func NewKleverAuthManager ¶
func NewKleverAuthManager(storedAddress string) *KleverAuthManager
NewKleverAuthManager creates a new KleverAuthManager with an optional stored address.
func (*KleverAuthManager) Address ¶
func (k *KleverAuthManager) Address() string
Address returns the registered admin address.
func (*KleverAuthManager) CreateChallenge ¶
func (k *KleverAuthManager) CreateChallenge(address string) (string, error)
CreateChallenge generates a random nonce for the given address. Returns the hex-encoded nonce.
func (*KleverAuthManager) CreateSetupChallenge ¶
func (k *KleverAuthManager) CreateSetupChallenge(address string) (string, error)
CreateSetupChallenge generates a nonce for any valid klv1... address (no registered address required). Used during wallet linking in settings to prove ownership before saving.
func (*KleverAuthManager) HasAddress ¶
func (k *KleverAuthManager) HasAddress() bool
HasAddress returns whether an admin address is configured.
func (*KleverAuthManager) RemoveAddress ¶
func (k *KleverAuthManager) RemoveAddress()
RemoveAddress removes the registered admin address.
func (*KleverAuthManager) SetAddress ¶
func (k *KleverAuthManager) SetAddress(address string) error
SetAddress registers a klv1... address as the admin wallet.
func (*KleverAuthManager) VerifySetupSignature ¶
func (k *KleverAuthManager) VerifySetupSignature(address, nonce, signature string) error
VerifySetupSignature verifies a signature for wallet linking (no registered address check). On success, the caller should save the address.
func (*KleverAuthManager) VerifySignature ¶
func (k *KleverAuthManager) VerifySignature(address, nonce, signature string) error
VerifySignature verifies an Ed25519 signature from the Klever Extension. The signature should be hex-encoded (128 hex chars = 64 bytes).
type PasskeyCredential ¶
type PasskeyCredential struct {
ID string `json:"id"` // Credential ID (hex-encoded)
PublicKey []byte `json:"public_key"` // COSE public key
Name string `json:"name"` // User-friendly name (e.g., "MacBook Pro")
SignCount uint32 `json:"sign_count"` // Signature counter (replay detection)
BackupEligible bool `json:"backup_eligible"` // Whether credential supports backup/sync
BackupState bool `json:"backup_state"` // Whether credential is currently backed up
RegisteredAt int64 `json:"registered_at"` // Unix timestamp
}
PasskeyCredential stores a registered WebAuthn credential.
type PasswordManager ¶
type PasswordManager struct {
// contains filtered or unexported fields
}
PasswordManager handles password-based authentication with Argon2id hashing.
func NewPasswordManager ¶
func NewPasswordManager(storedHash string) *PasswordManager
NewPasswordManager creates a new PasswordManager with an optional stored hash.
func (*PasswordManager) HasPassword ¶
func (pm *PasswordManager) HasPassword() bool
HasPassword returns true if a password has been set.
func (*PasswordManager) Hash ¶
func (pm *PasswordManager) Hash() string
Hash returns the current hash for persistence.
func (*PasswordManager) SetPassword ¶
func (pm *PasswordManager) SetPassword(password string) (string, error)
SetPassword hashes and stores a new password. Returns the hash for persistence.
func (*PasswordManager) Verify ¶
func (pm *PasswordManager) Verify(password string) bool
Verify checks a password against the stored hash.
type RateLimiter ¶
type RateLimiter struct {
// contains filtered or unexported fields
}
RateLimiter tracks failed login attempts per IP with a sliding window.
func NewRateLimiter ¶
func NewRateLimiter(window time.Duration, maxFails int) *RateLimiter
NewRateLimiter creates a rate limiter with the given window and max failures.
func (*RateLimiter) Allow ¶
func (rl *RateLimiter) Allow(ip string) bool
Allow checks if an IP is allowed to attempt a login.
func (*RateLimiter) RecordFailure ¶
func (rl *RateLimiter) RecordFailure(ip string)
RecordFailure records a failed login attempt for the given IP.
func (*RateLimiter) Reset ¶
func (rl *RateLimiter) Reset(ip string)
Reset clears the failure count for an IP after a successful login.
type RecoveryCode ¶
type RecoveryCode struct {
Hash string `json:"hash"` // Argon2id hash (hex-encoded: salt + hash)
Used bool `json:"used"`
}
RecoveryCode holds a hashed recovery code with its usage state.
type RecoveryManager ¶
type RecoveryManager struct {
// contains filtered or unexported fields
}
RecoveryManager handles generation, hashing, and verification of recovery codes.
func NewRecoveryManager ¶
func NewRecoveryManager(codes []RecoveryCode) *RecoveryManager
NewRecoveryManager creates a new RecoveryManager with the given stored codes.
func (*RecoveryManager) Codes ¶
func (rm *RecoveryManager) Codes() []RecoveryCode
Codes returns the current stored codes (for persistence).
func (*RecoveryManager) GenerateCodes ¶
func (rm *RecoveryManager) GenerateCodes() (plaintextCodes []string, hashedCodes []RecoveryCode, err error)
GenerateCodes generates a new set of recovery codes. Returns the plaintext codes (to show the user once) and the hashed codes (to store).
func (*RecoveryManager) Remaining ¶
func (rm *RecoveryManager) Remaining() int
Remaining returns the number of unused recovery codes.
func (*RecoveryManager) Verify ¶
func (rm *RecoveryManager) Verify(code string) bool
Verify checks a recovery code against stored hashes. If valid, the code is marked as used and cannot be reused. Returns true if the code was valid and unused.
type TokenPair ¶
type TokenPair struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int64 `json:"expires_in"` // seconds
}
TokenPair holds an access token and refresh token.
type WebAuthnConfig ¶
type WebAuthnConfig struct {
RPDisplayName string // Relying Party display name (e.g., "Klever Node Hub")
RPID string // Relying Party ID (e.g., "localhost" or domain)
RPOrigins []string // Allowed origins (e.g., "https://localhost:9443")
InstanceID string // Unique ID for this dashboard instance (prevents passkey collisions when multiple dashboards share the same RP ID)
}
WebAuthnConfig holds configuration for WebAuthn initialization.
type WebAuthnManager ¶
type WebAuthnManager struct {
// contains filtered or unexported fields
}
WebAuthnManager handles passkey registration and authentication.
func NewWebAuthnManager ¶
func NewWebAuthnManager(config WebAuthnConfig, credentials []PasskeyCredential) (*WebAuthnManager, error)
NewWebAuthnManager creates a new WebAuthn manager.
func (*WebAuthnManager) BeginLogin ¶
func (wm *WebAuthnManager) BeginLogin() (*protocol.CredentialAssertion, string, error)
BeginLogin starts a passkey authentication ceremony.
func (*WebAuthnManager) BeginRegistration ¶
func (wm *WebAuthnManager) BeginRegistration(passkeyName string) (*protocol.CredentialCreation, string, error)
BeginRegistration starts a passkey registration ceremony. Returns the options to send to the browser and a session ID.
func (*WebAuthnManager) CredentialCount ¶
func (wm *WebAuthnManager) CredentialCount() int
CredentialCount returns the number of registered passkeys.
func (*WebAuthnManager) Credentials ¶
func (wm *WebAuthnManager) Credentials() []PasskeyCredential
Credentials returns the current stored credentials (for persistence).
func (*WebAuthnManager) DeletePasskey ¶
func (wm *WebAuthnManager) DeletePasskey(id string) error
DeletePasskey removes a passkey by ID. Enforces minimum 1 passkey.
func (*WebAuthnManager) FinishLogin ¶
func (wm *WebAuthnManager) FinishLogin(sessionID string, response *protocol.ParsedCredentialAssertionData) error
FinishLogin completes a passkey authentication ceremony.
func (*WebAuthnManager) FinishRegistration ¶
func (wm *WebAuthnManager) FinishRegistration(sessionID string, response *protocol.ParsedCredentialCreationData, name string) error
FinishRegistration completes a passkey registration ceremony.
func (*WebAuthnManager) HasCredentials ¶
func (wm *WebAuthnManager) HasCredentials() bool
HasCredentials returns true if at least one passkey is registered.