auth

package module
v0.0.0-...-e5a810f Latest Latest
Warning

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

Go to latest
Published: Nov 4, 2025 License: BSD-3-Clause Imports: 16 Imported by: 0

README

Auth Package

Modular authentication utilities for Go applications.

Features

  • Password Hashing: Standalone Argon2id hashing with PHC format.
  • JWT: HS256/RS256 token management via a simple facade over golang-jwt.
  • SCRAM-SHA256: Client/server implementation with Argon2id KDF.
  • HTTP Auth: Helpers for parsing Basic and Bearer authentication headers.

Usage

// Argon2 Password Hashing
hash, _ := auth.HashPassword("password123")
err := auth.VerifyPassword("password123", hash)

// JWT with HS256
jwtMgr, _ := auth.NewJWT([]byte("a-very-secure-32-byte-secret-key"))
token, _ := jwtMgr.GenerateToken("user123", map[string]any{"role": "admin"})
userID, claims, _ := jwtMgr.ValidateToken(token)

// SCRAM authentication
server := auth.NewScramServer()
phcHash, _ := auth.HashPassword("password123")
cred, _ := auth.MigrateFromPHC("user", "password123", phcHash)
server.AddCredential(cred)

Package Structure

  • doc.go - Overview and package documentation
  • argon2.go - Standalone Argon2id password hashing
  • jwt.go - JWT manager (HS256/RS256) wrapping golang-jwt
  • scram.go - SCRAM-SHA256 client/server protocol
  • http.go - HTTP Basic/Bearer header parsing
  • token.go - Simple in-memory token validator
  • error.go - Centralized error definitions

Testing

go test -v ./

Documentation

Overview

FILE: auth/argon2.go

FILE: auth/doc.go

FILE: auth/errors.go

FILE: auth/http.go

FILE: auth/jwt.go

FILE: auth/scram.go

FILE: auth/token.go

Index

Constants

View Source
const (
	DefaultArgonTime    = 3         // iterations
	DefaultArgonMemory  = 64 * 1024 // 64 MB
	DefaultArgonThreads = 4
	DefaultArgonSaltLen = 16
	DefaultArgonKeyLen  = 32
)

Default Argon2id parameters

View Source
const (
	DefaultTokenLifetime = 24 * time.Hour
	DefaultLeeway        = 5 * time.Minute
)

JWT configuration defaults

View Source
const (
	// ScramHandshakeTimeout defines maximum time for completing SCRAM handshake
	ScramHandshakeTimeout = 30 * time.Second
	// ScramCleanupInterval defines how often expired handshakes are cleaned
	ScramCleanupInterval = 60 * time.Second
)

Variables

View Source
var (
	ErrInvalidCredentials = errors.New("invalid credentials")
	ErrWeakPassword       = errors.New("password must be at least 8 characters")
)

Base authentication errors

View Source
var (
	ErrTokenMalformed         = errors.New("token: malformed structure")
	ErrTokenExpired           = errors.New("token: expired")
	ErrTokenNotYetValid       = errors.New("token: not yet valid")
	ErrTokenInvalidSignature  = errors.New("token: invalid signature")
	ErrTokenAlgorithmMismatch = errors.New("token: algorithm mismatch")
	ErrTokenMissingClaim      = errors.New("token: missing required claim")
	ErrTokenEmptyUserID       = errors.New("token: empty user ID")
	ErrTokenNoPrivateKey      = errors.New("token: private key required for signing")
	ErrTokenNoPublicKey       = errors.New("token: public key required for verification")
)

JWT-specific errors

View Source
var (
	ErrRSAInvalidPEM        = errors.New("rsa: failed to parse PEM block")
	ErrRSAInvalidPrivateKey = errors.New("rsa: invalid private key format")
	ErrRSAInvalidPublicKey  = errors.New("rsa: invalid public key format")
	ErrRSANotPublicKey      = errors.New("rsa: not an RSA public key")
)

RSA key parsing errors

View Source
var (
	ErrPHCInvalidFormat = errors.New("phc: invalid format")
	ErrPHCInvalidSalt   = errors.New("phc: invalid salt encoding")
	ErrPHCInvalidHash   = errors.New("phc: invalid hash encoding")
)

PHC format errors

View Source
var (
	ErrSCRAMInvalidNonce     = errors.New("scram: invalid nonce or expired handshake")
	ErrSCRAMTimeout          = errors.New("scram: handshake timeout")
	ErrSCRAMVerifyInProgress = errors.New("scram: verification already in progress")
	ErrSCRAMInvalidProof     = errors.New("scram: invalid proof encoding")
	ErrSCRAMInvalidProofLen  = errors.New("scram: invalid proof length")
	ErrSCRAMServerAuthFailed = errors.New("scram: server authentication failed")
	ErrSCRAMInvalidState     = errors.New("scram: invalid handshake state")
	ErrSCRAMInvalidSalt      = errors.New("scram: invalid salt encoding")
	ErrSCRAMZeroParams       = errors.New("scram: invalid Argon2 parameters")
	ErrSCRAMSaltTooShort     = errors.New("scram: salt must be at least 16 bytes")
	ErrSCRAMNonceGenFailed   = errors.New("scram: failed to generate nonce")
)

SCRAM-specific errors

View Source
var (
	ErrCredMissingUsername  = errors.New("credential: missing username")
	ErrCredMissingSalt      = errors.New("credential: missing salt")
	ErrCredInvalidSalt      = errors.New("credential: invalid salt encoding")
	ErrCredMissingTime      = errors.New("credential: missing argon_time")
	ErrCredMissingMemory    = errors.New("credential: missing argon_memory")
	ErrCredMissingThreads   = errors.New("credential: missing argon_threads")
	ErrCredMissingStoredKey = errors.New("credential: missing stored_key")
	ErrCredInvalidStoredKey = errors.New("credential: invalid stored_key encoding")
	ErrCredMissingServerKey = errors.New("credential: missing server_key")
	ErrCredInvalidServerKey = errors.New("credential: invalid server_key encoding")
	ErrCredInvalidType      = fmt.Errorf("credential: invalid type for field")
)

Credential import/export errors

View Source
var (
	ErrAuthInvalidBasicFormat   = errors.New("auth: invalid Basic auth format")
	ErrAuthInvalidBasicEncoding = errors.New("auth: invalid Basic auth base64 encoding")
	ErrAuthInvalidBasicCreds    = errors.New("auth: invalid Basic auth credentials format")
	ErrAuthInvalidBearerFormat  = errors.New("auth: invalid Bearer auth format")
	ErrAuthEmptyBearerToken     = errors.New("auth: empty Bearer token")
)

HTTP auth parsing errors

View Source
var (
	ErrRSAKeyGenFailed = errors.New("failed to generate RSA key")
)

Key generation errors

View Source
var (
	ErrSaltGenerationFailed = errors.New("failed to generate salt")
)

Salt generation errors

View Source
var (
	ErrSecretTooShort = errors.New("JWT secret must be at least 32 bytes")
)

JWT secret errors

Functions

func ExtractAuthType

func ExtractAuthType(header string) string

ExtractAuthType returns authentication type from header

func GenerateHS256Token

func GenerateHS256Token(secret []byte, userID string, claims map[string]any, lifetime time.Duration) (string, error)

GenerateHS256Token creates HS256 JWT without manager instance

func HashPassword

func HashPassword(password string, opts ...Option) (string, error)

HashPassword creates Argon2id PHC-format hash (standalone)

func ParseBasicAuth

func ParseBasicAuth(header string) (username, password string, err error)

ParseBasicAuth extracts username/password from Basic auth header

func ParseBearerToken

func ParseBearerToken(header string) (token string, err error)

ParseBearerToken extracts token from Bearer auth header

func ValidateHS256Token

func ValidateHS256Token(secret []byte, tokenString string) (string, map[string]any, error)

ValidateHS256Token verifies HS256 JWT without manager instance

func ValidatePHCHashFormat

func ValidatePHCHashFormat(phcHash string) error

ValidatePHCHashFormat checks if a hash string has a valid and complete PHC format for Argon2id. It validates structure, parameters, and encoding, but does not verify a password against the hash.

func VerifyPassword

func VerifyPassword(password, phcHash string) error

VerifyPassword checks password against PHC-format hash (standalone)

Types

type ClientFinalRequest

type ClientFinalRequest struct {
	FullNonce   string `json:"full_nonce"`
	ClientProof string `json:"client_proof"`
}

type ClientFirstRequest

type ClientFirstRequest struct {
	Username    string `json:"username"`
	ClientNonce string `json:"client_nonce"`
}

SCRAM message types

type Credential

type Credential struct {
	Username     string
	Salt         []byte
	ArgonTime    uint32
	ArgonMemory  uint32
	ArgonThreads uint8
	StoredKey    []byte // SHA256(ClientKey)
	ServerKey    []byte
}

Credential stores SCRAM authentication data

func DeriveCredential

func DeriveCredential(username, password string, salt []byte, time, memory uint32, threads uint8) (*Credential, error)

DeriveCredential creates SCRAM credential from password

func ImportCredential

func ImportCredential(data map[string]any) (*Credential, error)

ImportCredential creates credential from map

func MigrateFromPHC

func MigrateFromPHC(username, password, phcHash string) (*Credential, error)

MigrateFromPHC converts PHC hash to SCRAM credential

func (*Credential) Export

func (c *Credential) Export() map[string]any

Export returns credential as config-friendly map

type HandshakeState

type HandshakeState struct {
	Username    string
	ClientNonce string
	ServerNonce string
	FullNonce   string
	Credential  *Credential
	CreatedAt   time.Time
	// contains filtered or unexported fields
}

HandshakeState tracks ongoing authentication

type JWT

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

JWT manages token generation and validation

func NewJWT

func NewJWT(secret []byte, opts ...JWTOption) (*JWT, error)

NewJWT creates JWT manager for HS256 (symmetric)

func NewJWTRSA

func NewJWTRSA(privateKey *rsa.PrivateKey, opts ...JWTOption) (*JWT, error)

NewJWTRSA creates JWT manager for RS256 (asymmetric)

func NewJWTRSAFromPEM

func NewJWTRSAFromPEM(privateKeyPEM []byte, opts ...JWTOption) (*JWT, error)

NewJWTRSAFromPEM creates a JWT manager for RS256 from raw PEM-encoded private key data.

func NewJWTVerifier

func NewJWTVerifier(publicKey *rsa.PublicKey, opts ...JWTOption) (*JWT, error)

NewJWTVerifier creates JWT manager for verification only (RS256)

func NewJWTVerifierFromPEM

func NewJWTVerifierFromPEM(publicKeyPEM []byte, opts ...JWTOption) (*JWT, error)

NewJWTVerifierFromPEM creates a JWT manager for verification from raw PEM-encoded public key data.

func (*JWT) GenerateToken

func (j *JWT) GenerateToken(userID string, claims map[string]any) (string, error)

GenerateToken creates signed JWT with claims

func (*JWT) ValidateToken

func (j *JWT) ValidateToken(tokenString string) (string, map[string]any, error)

ValidateToken verifies JWT and extracts claims

type JWTOption

type JWTOption func(*JWT)

JWTOption configures JWT behavior

func WithAudience

func WithAudience(aud []string) JWTOption

WithAudience sets token audience claim

func WithIssuer

func WithIssuer(iss string) JWTOption

WithIssuer sets token issuer claim

func WithLeeway

func WithLeeway(d time.Duration) JWTOption

WithLeeway sets clock skew tolerance

func WithTokenLifetime

func WithTokenLifetime(d time.Duration) JWTOption

WithTokenLifetime sets token expiration duration

type Option

type Option func(*argonParams)

Option configures Argon2id hashing parameters

func WithMemory

func WithMemory(m uint32) Option

WithMemory sets Argon2 memory in KiB

func WithThreads

func WithThreads(t uint8) Option

WithThreads sets Argon2 parallelism

func WithTime

func WithTime(t uint32) Option

WithTime sets Argon2 iterations

type ScramClient

type ScramClient struct {
	Username string
	Password string
	// contains filtered or unexported fields
}

ScramClient handles client-side SCRAM authentication

func NewScramClient

func NewScramClient(username, password string) *ScramClient

NewScramClient creates SCRAM client

func (*ScramClient) ProcessServerFirstMessage

func (c *ScramClient) ProcessServerFirstMessage(msg ServerFirstMessage) (ClientFinalRequest, error)

ProcessServerFirstMessage handles server challenge

func (*ScramClient) Reset

func (c *ScramClient) Reset()

Reset clears client state for retry

func (*ScramClient) StartAuthentication

func (c *ScramClient) StartAuthentication() (ClientFirstRequest, error)

StartAuthentication generates initial client message

func (*ScramClient) VerifyServerFinalMessage

func (c *ScramClient) VerifyServerFinalMessage(msg ServerFinalMessage) error

VerifyServerFinalMessage validates server signature

type ScramServer

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

ScramServer handles server-side SCRAM authentication

func NewScramServer

func NewScramServer() *ScramServer

NewScramServer creates SCRAM server

func (*ScramServer) AddCredential

func (s *ScramServer) AddCredential(cred *Credential)

AddCredential registers user credential

func (*ScramServer) ProcessClientFinalMessage

func (s *ScramServer) ProcessClientFinalMessage(fullNonce, clientProof string) (ServerFinalMessage, error)

ProcessClientFinalMessage verifies client proof

func (*ScramServer) ProcessClientFirstMessage

func (s *ScramServer) ProcessClientFirstMessage(username, clientNonce string) (ServerFirstMessage, error)

ProcessClientFirstMessage processes initial auth request

func (*ScramServer) Stop

func (s *ScramServer) Stop()

Stop gracefully shuts down the server and cleanup goroutine

type ServerFinalMessage

type ServerFinalMessage struct {
	ServerSignature string `json:"server_signature"`
	Username        string `json:"username,omitempty"`
}

type ServerFirstMessage

type ServerFirstMessage struct {
	FullNonce    string `json:"full_nonce"`
	Salt         string `json:"salt"`
	ArgonTime    uint32 `json:"argon_time"`
	ArgonMemory  uint32 `json:"argon_memory"`
	ArgonThreads uint8  `json:"argon_threads"`
}

func (ServerFirstMessage) Marshal

func (s ServerFirstMessage) Marshal() string

type SimpleTokenValidator

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

SimpleTokenValidator implements in-memory token validation

func NewSimpleTokenValidator

func NewSimpleTokenValidator() *SimpleTokenValidator

NewSimpleTokenValidator creates token validator

func (*SimpleTokenValidator) AddToken

func (v *SimpleTokenValidator) AddToken(token string)

AddToken adds token to validator

func (*SimpleTokenValidator) RemoveToken

func (v *SimpleTokenValidator) RemoveToken(token string)

RemoveToken removes token from validator

func (*SimpleTokenValidator) ValidateToken

func (v *SimpleTokenValidator) ValidateToken(token string) bool

ValidateToken checks if token is valid

Jump to

Keyboard shortcuts

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