challenge

package
v0.0.0-...-0560ca3 Latest Latest
Warning

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

Go to latest
Published: Jul 4, 2026 License: MIT Imports: 36 Imported by: 0

Documentation

Index

Constants

View Source
const (
	RequestOptBackendHost       = "backend-host"
	RequestOptProxyMetaTags     = "proxy-meta-tags"
	RequestOptProxySafeLinkTags = "proxy-safe-link-tags"
)
View Source
const (
	QueryArgPrefix    = "__goaway"
	QueryArgReferer   = QueryArgPrefix + "_referer"
	QueryArgRedirect  = QueryArgPrefix + "_redirect"
	QueryArgRequestId = QueryArgPrefix + "_id"
	QueryArgChallenge = QueryArgPrefix + "_challenge"
	QueryArgToken     = QueryArgPrefix + "_token"
	QueryArgBust      = QueryArgPrefix + "_bust"
)
View Source
const (
	// ClassTransparent Transparent challenges work inline in the execution process.
	// These can pass or continue, so more challenges or requests can ve served afterward.
	ClassTransparent = Class(iota)

	// ClassBlocking Blocking challenges must serve a different response to challenge the requester.
	// These can pass or stop, for example, due to serving a challenge
	ClassBlocking
)
View Source
const (
	VerifyStateNone = VerifyState(iota)
	// VerifyStatePass Challenge was just passed on this request
	VerifyStatePass
	// VerifyStateBrief Challenge token was verified but didn't check the challenge
	VerifyStateBrief
	// VerifyStateFull Challenge token was verified and challenge verification was done
	VerifyStateFull
)
View Source
const (
	// VerifyResultNone A negative pass result, without a token
	VerifyResultNone = VerifyResult(iota)
	// VerifyResultFail A negative pass result, with an invalid token
	VerifyResultFail
	// VerifyResultSkip Challenge was skipped due to precondition
	VerifyResultSkip
	// VerifyResultNotOK A negative pass result, with a valid token
	VerifyResultNotOK

	// VerifyResultOK A positive pass result, with a valid token
	VerifyResultOK
)
View Source
const DefaultDuration = time.Hour * 24 * 7

DefaultDuration TODO: adjust

View Source
const (
	KeyFlagIsIPv4 = KeyFlags(1 << iota)
)
View Source
const KeySize = sha256.Size
View Source
const MakeChallengeUrlSuffix = "/make-challenge"
View Source
const VerifyChallengeUrlSuffix = "/verify-challenge"

Variables

View Source
var DefaultKeyHeaders = []string{

	"User-Agent",

	"Accept-Language",
	"Accept-Encoding",

	"Sec-Ch-Ua",
	"Sec-Ch-Ua-Platform",
}
View Source
var ErrInvalidToken = errors.New("invalid token")
View Source
var ErrMismatchedToken = errors.New("mismatched token")
View Source
var ErrMismatchedTokenHappyEyeballs = errors.New("mismatched token: IPv4 to IPv6 upgrade detected, retrying")
View Source
var ErrTokenExpired = errors.New("token: expired")
View Source
var ErrVerifyKeyMismatch = errors.New("verify: key mismatch")
View Source
var ErrVerifyVerifyMismatch = errors.New("verify: verification mismatch")
View Source
var MinimalKeyHeaders = []string{
	"Accept-Language",

	"User-Agent",
}
View Source
var Runtimes = make(map[string]FillRegistration)

Functions

func RedirectUrl

func RedirectUrl(r *http.Request, reg *Registration) (*url.URL, error)

func ServeChallengeScript

func ServeChallengeScript(w http.ResponseWriter, r *http.Request, reg *Registration, params any, script string)

func VerifyHandlerChallengeResponseFunc

func VerifyHandlerChallengeResponseFunc(state StateInterface, data *RequestData, w http.ResponseWriter, r *http.Request, verifyResult VerifyResult, err error, redirect string)

func VerifyHandlerFunc

func VerifyHandlerFunc(state StateInterface, reg *Registration, verify VerifyFunc, responseFunc func(state StateInterface, data *RequestData, w http.ResponseWriter, r *http.Request, verifyResult VerifyResult, err error, redirect string)) http.HandlerFunc

func VerifyUrl

func VerifyUrl(r *http.Request, reg *Registration, token string) (*url.URL, error)

Types

type Awaiter

type Awaiter[K ~string | ~int64 | ~uint64] haxmap.Map[K, awaiterCallback]

func NewAwaiter

func NewAwaiter[T ~string | ~int64 | ~uint64]() *Awaiter[T]

func (*Awaiter[T]) Await

func (a *Awaiter[T]) Await(key T, ctx context.Context) VerifyResult

func (*Awaiter[T]) Close

func (a *Awaiter[T]) Close() error

func (*Awaiter[T]) Solve

func (a *Awaiter[T]) Solve(key T, result VerifyResult)

type Class

type Class uint8

type FillRegistration

type FillRegistration func(state StateInterface, reg *Registration, parameters ast.Node) error

type Id

type Id int64

type Key

type Key [KeySize]byte

func GetChallengeKeyForRequest

func GetChallengeKeyForRequest(state StateInterface, reg *Registration, until time.Time, r *http.Request) Key

func KeyFromString

func KeyFromString(s string) (Key, error)

func (*Key) Get

func (k *Key) Get(flags KeyFlags) KeyFlags

func (*Key) Set

func (k *Key) Set(flags KeyFlags)

func (*Key) Unset

func (k *Key) Unset(flags KeyFlags)

type KeyFlags

type KeyFlags uint8

type Register

type Register map[Id]*Registration

func (Register) Add

func (r Register) Add(c *Registration) Id

func (Register) Create

func (r Register) Create(state StateInterface, name string, pol policy.Challenge, replacer *strings.Replacer) (*Registration, Id, error)

func (Register) Get

func (r Register) Get(id Id) (*Registration, bool)

func (Register) GetByName

func (r Register) GetByName(name string) (*Registration, Id, bool)

type Registration

type Registration struct {

	// Name The unique name for this challenge
	Name string

	// Class whether this challenge is transparent or otherwise
	Class Class

	// Condition A CEL condition which is passed the same environment as general rules.
	// If nil, always true
	// If non-nil, must return true for this challenge to be allowed to be executed
	Condition cel.Program

	// Path The url path that this challenge is hosted under for the Handler to be called.
	Path string

	// Duration How long this challenge will be valid when passed
	Duration time.Duration

	// Handler An HTTP handler for all requests coming on the Path
	// This handler will need to handle MakeChallengeUrlSuffix and VerifyChallengeUrlSuffix as well if needed
	// Recommended to use http.ServeMux
	Handler http.Handler

	// Verify Verify an issued token
	Verify            VerifyFunc
	VerifyProbability float64

	// KeyHeaders The client headers used in key generation, in this order
	KeyHeaders []string

	// IssueChallenge Issues a challenge to a request.
	// If Class is ClassTransparent and VerifyResult is !VerifyResult.Ok(), continue with other challenges
	// TODO: have this return error as well
	IssueChallenge func(w http.ResponseWriter, r *http.Request, key Key, expiry time.Time) VerifyResult

	// Object used to handle state or similar
	// Can be nil if no state is needed
	// If non-nil must implement io.Closer even if there's nothing to do
	Object io.Closer
	// contains filtered or unexported fields
}

func (Registration) Id

func (reg Registration) Id() Id

type RequestData

type RequestData struct {
	Id              RequestId
	Time            time.Time
	ChallengeVerify map[Id]VerifyResult
	ChallengeState  map[Id]VerifyState
	ChallengeMap    TokenChallengeMap

	RemoteAddress netip.AddrPort
	State         StateInterface

	ExtraHeaders http.Header
	// contains filtered or unexported fields
}

func CreateRequestData

func CreateRequestData(r *http.Request, state StateInterface) (*http.Request, *RequestData)

func RequestDataFromContext

func RequestDataFromContext(ctx context.Context) *RequestData

func (*RequestData) BackendHost

func (d *RequestData) BackendHost() (http.Handler, string)

func (*RequestData) ClearChallengeToken

func (d *RequestData) ClearChallengeToken(reg *Registration)

func (*RequestData) EvaluateChallenges

func (d *RequestData) EvaluateChallenges(w http.ResponseWriter, r *http.Request)

func (*RequestData) Expiration

func (d *RequestData) Expiration(duration time.Duration) time.Time

func (*RequestData) GetOpt

func (d *RequestData) GetOpt(n, def string) string

func (*RequestData) GetOptBool

func (d *RequestData) GetOptBool(n string, def bool) bool

func (*RequestData) HasValidChallenge

func (d *RequestData) HasValidChallenge(id Id) bool

func (*RequestData) IssueChallengeToken

func (d *RequestData) IssueChallengeToken(reg *Registration, key Key, result []byte, until time.Time, ok bool)

func (*RequestData) NetworkPrefix

func (d *RequestData) NetworkPrefix() netip.Addr

func (*RequestData) Parent

func (d *RequestData) Parent() cel.Activation

func (*RequestData) RequestHeaders

func (d *RequestData) RequestHeaders(headers http.Header)

func (*RequestData) ResolveName

func (d *RequestData) ResolveName(name string) (any, bool)

func (*RequestData) ResponseHeaders

func (d *RequestData) ResponseHeaders(w http.ResponseWriter)

func (*RequestData) SetOpt

func (d *RequestData) SetOpt(n, v string)

func (*RequestData) VerifyChallengeToken

func (d *RequestData) VerifyChallengeToken(reg *Registration, token TokenChallenge, expectedKey Key) (VerifyResult, VerifyState, error)

type RequestId

type RequestId [16]byte

func GetVerifyInformation

func GetVerifyInformation(r *http.Request, reg *Registration) (requestId RequestId, redirect, token string, err error)

func (RequestId) String

func (id RequestId) String() string

type StateInterface

type StateInterface interface {
	RegisterCondition(operator string, conditions ...string) (cel.Program, error)

	Client() *http.Client
	PrivateKeyFingerprint() []byte
	PrivateKey() ed25519.PrivateKey
	PublicKey() ed25519.PublicKey

	UrlPath() string

	ChallengeFailed(r *http.Request, reg *Registration, err error, redirect string, logger *slog.Logger)
	ChallengePassed(r *http.Request, reg *Registration, redirect string, logger *slog.Logger)
	ChallengeIssued(r *http.Request, reg *Registration, redirect string, logger *slog.Logger)
	ChallengeChecked(r *http.Request, reg *Registration, redirect string, logger *slog.Logger)

	RuleHit(r *http.Request, name string, logger *slog.Logger)
	RuleMiss(r *http.Request, name string, logger *slog.Logger)
	ActionHit(r *http.Request, name policy.RuleAction, logger *slog.Logger)

	Logger(r *http.Request) *slog.Logger

	ChallengePage(w http.ResponseWriter, r *http.Request, status int, reg *Registration, params map[string]any)
	ErrorPage(w http.ResponseWriter, r *http.Request, status int, err error, redirect string)

	GetChallenge(id Id) (*Registration, bool)
	GetChallengeByName(name string) (*Registration, bool)
	GetChallenges() Register

	Settings() policy.StateSettings

	Strings() utils.Strings

	GetBackend(host string) http.Handler
}

type Token

type Token struct {
	State TokenChallengeMap `json:"state"`

	Expiry    jwt.NumericDate `json:"exp,omitempty"`
	NotBefore jwt.NumericDate `json:"nbf,omitempty"`
	IssuedAt  jwt.NumericDate `json:"iat,omitempty"`
}

type TokenChallenge

type TokenChallenge struct {
	Key    []byte `json:"key"`
	Result []byte `json:"result,omitempty"`
	Ok     bool   `json:"ok"`

	Expiry    jwt.NumericDate `json:"exp,omitempty"`
	NotBefore jwt.NumericDate `json:"nbf,omitempty"`
	IssuedAt  jwt.NumericDate `json:"iat,omitempty"`
}

type TokenChallengeMap

type TokenChallengeMap map[string]TokenChallenge

type VerifyFunc

type VerifyFunc func(key Key, token []byte, r *http.Request) (VerifyResult, error)

func NewKeyVerifier

func NewKeyVerifier() (verify VerifyFunc, issue func(key Key) string)

type VerifyResult

type VerifyResult uint8

func (VerifyResult) Ok

func (r VerifyResult) Ok() bool

func (VerifyResult) String

func (r VerifyResult) String() string

type VerifyState

type VerifyState uint8

func (VerifyState) String

func (r VerifyState) String() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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