auth

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Jun 29, 2026 License: AGPL-3.0 Imports: 13 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrChallengeNotFound indicates the requested challenge does not exist or has expired.
	ErrChallengeNotFound = errors.New("challenge not found")

	// ErrChallengeExpired indicates the challenge has exceeded its validity period.
	ErrChallengeExpired = errors.New("challenge expired")

	// ErrInvalidTransaction indicates the provided transaction is malformed or invalid.
	ErrInvalidTransaction = errors.New("invalid transaction")

	// ErrTransactionMismatch indicates the signed transaction does not match the original challenge.
	ErrTransactionMismatch = errors.New("transaction does not match challenge")

	// ErrInvalidSignature indicates the transaction is not signed by the expected keypair.
	ErrInvalidSignature = errors.New("invalid or missing signature")

	// ErrInvalidToken indicates the JWT token is malformed, expired, or has an invalid signature.
	ErrInvalidToken = errors.New("invalid token")

	// ErrInvalidTokenClaims indicates the token claims are invalid or cannot be parsed.
	ErrInvalidTokenClaims = errors.New("invalid token claims")

	// ErrUnexpectedSigningMethod indicates the token uses an unsupported signing algorithm.
	ErrUnexpectedSigningMethod = errors.New("unexpected signing method")
)

Authentication errors that can be mapped to HTTP status codes by handlers.

Functions

This section is empty.

Types

type Challenge

type Challenge struct {
	ID          string    `json:"id"`          // Unique identifier for the challenge
	Transaction string    `json:"transaction"` // Base64-encoded Stellar transaction envelope
	CreatedAt   time.Time `json:"created_at"`  // Timestamp when the challenge was created
	ExpiresAt   time.Time `json:"expires_at"`  // Timestamp when the challenge expires
}

Challenge represents a cryptographic challenge used in the authentication flow. It contains a Stellar transaction that must be signed by the user to prove ownership of their private key. Challenges are temporary and expire after a configured duration.

type ChallengeService

type ChallengeService interface {
	// GenerateChallenge creates a new authentication challenge containing a Stellar transaction
	// that must be signed by the user. The challenge expires after a configured duration.
	GenerateChallenge() (*Challenge, error)

	// VerifySignedChallenge validates that the provided transaction was signed by the correct
	// keypair and matches the original challenge. Challenges are single-use and deleted after verification.
	VerifySignedChallenge(challengeID, signedTxB64 string) error
}

ChallengeService defines the interface for Stellar transaction-based challenge-response authentication. This implements a cryptographic proof-of-ownership flow where users must sign a server-generated Stellar transaction with their private key to prove they control a specific public key.

func NewChallengeService

func NewChallengeService(authConfig *config.AuthConfig, stellarConfig *config.StellarConfig, store ChallengeStore) (ChallengeService, error)

NewChallengeService creates a new ChallengeService with the provided configuration. The serverSecret is the Stellar private key used to sign challenges, proving they originated from the server. Returns an error if the serverSecret is not a valid Stellar private key.

type ChallengeStore

type ChallengeStore interface {
	// Store persists a challenge with automatic expiration based on the challenge's ExpiresAt field.
	// Returns an error if the challenge is already expired or if storage fails.
	Store(challengeID string, challenge *Challenge) error

	// Get retrieves a challenge by its ID. Returns an error if the challenge is not found,
	// has expired, or if retrieval fails.
	Get(challengeID string) (*Challenge, error)

	// Delete removes a challenge from storage. This should be called after successful
	// authentication to prevent challenge reuse. Returns an error if deletion fails.
	Delete(challengeID string) error
}

ChallengeStore defines the interface for storing and retrieving authentication challenges. Implementations must provide thread-safe operations with automatic expiration support.

func NewRedisStore

func NewRedisStore(client *redis.Client, keyPrefix string) (ChallengeStore, error)

NewRedisStore creates a new RedisStore instance for storing authentication challenges. The keyPrefix parameter is used to namespace challenge keys in Redis, allowing multiple applications or environments to share the same Redis instance without key collisions.

Example:

store := NewRedisStore(redisClient, "microvault:auth")
// This will create keys like: "microvault:auth:challenge:abc123"

type Claims

type Claims struct {
	AdminPublicKey string `json:"admin_pk"`
	jwt.RegisteredClaims
}

Claims represents the JWT token payload containing user authentication information. It embeds the standard JWT registered claims and adds the admin's Stellar public key.

type JWTService

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

JWTService provides JWT token generation and validation functionality. It uses HMAC-SHA256 signing and includes configurable expiration and refresh windows.

func NewJWTService

func NewJWTService(config *config.AuthConfig) *JWTService

NewJWTService creates a new JWTService instance with the provided authentication configuration.

func (*JWTService) GenerateToken

func (s *JWTService) GenerateToken(adminPublicKey string) (string, time.Time, error)

GenerateToken creates a new JWT token for the specified admin public key. The token is signed using HMAC-SHA256 and includes standard claims (issuer, subject, timestamps). Returns the signed token string, expiration time, and any error encountered during generation.

func (*JWTService) ShouldRefresh

func (s *JWTService) ShouldRefresh(claims *Claims) bool

ShouldRefresh determines if a token should be refreshed based on its remaining lifetime. Returns true if the token will expire within the configured refresh window, allowing clients to obtain a new token before the current one expires.

func (*JWTService) ValidateToken

func (s *JWTService) ValidateToken(tokenString string) (*Claims, error)

ValidateToken parses and validates a JWT token string. It verifies the signature using HMAC-SHA256 and ensures the token hasn't expired. Returns the extracted claims if valid, or an error if validation fails.

type RedisStore

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

RedisStore is a Redis-backed implementation of ChallengeStore. It uses Redis's native TTL functionality for automatic challenge expiration.

func (*RedisStore) Delete

func (s *RedisStore) Delete(challengeID string) error

Delete removes a challenge from Redis by its ID. This method should be called after successful authentication to prevent replay attacks where an attacker might try to reuse a valid signed challenge.

Returns an error if:

  • Redis DEL operation fails
  • The operation times out (3 second timeout)

Note: This method does not return an error if the challenge doesn't exist. DEL operations in Redis are idempotent.

func (*RedisStore) Get

func (s *RedisStore) Get(challengeID string) (*Challenge, error)

Get retrieves a challenge from Redis by its ID. The challenge data is retrieved from Redis and deserialized from JSON.

Returns an error if:

  • The challenge is not found (may have expired or never existed)
  • Redis GET operation fails
  • JSON unmarshaling fails
  • The operation times out (3 second timeout)

Note: If a challenge has expired, Redis will automatically delete it and this method will return a "challenge not found" error.

func (*RedisStore) Store

func (s *RedisStore) Store(challengeID string, challenge *Challenge) error

Store persists a challenge to Redis with automatic expiration. The challenge is serialized to JSON and stored with a TTL based on the ExpiresAt field. Redis will automatically remove the challenge when the TTL expires.

Returns an error if:

  • The challenge is already expired (ExpiresAt is in the past)
  • JSON marshaling fails
  • Redis SET operation fails
  • The operation times out (3 second timeout)

Jump to

Keyboard shortcuts

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