feat: implement challenge registry (#607)

* feat: implement challenge method registry

This paves the way for implementing a no-js check method (#95) by making
the challenge providers more generic.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib/challenge): rename proof-of-work package to proofofwork

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): make validated challenges a CounterVec

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): annotate jwts with challenge method

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib/challenge/proofofwork): implement tests

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib): add smoke tests for known good and known bad config files

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): use challenge.Impl#Issue when issuing challenges

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
Xe Iaso 2025-06-03 22:01:58 -04:00 committed by GitHub
parent ba4412c907
commit f2db43ad4b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 480 additions and 132 deletions

37
lib/challenge/error.go Normal file
View file

@ -0,0 +1,37 @@
package challenge
import (
"errors"
"fmt"
"net/http"
)
var (
ErrFailed = errors.New("challenge: user failed challenge")
ErrMissingField = errors.New("challenge: missing field")
ErrInvalidFormat = errors.New("challenge: field has invalid format")
)
func NewError(verb, publicReason string, privateReason error) *Error {
return &Error{
Verb: verb,
PublicReason: publicReason,
PrivateReason: privateReason,
StatusCode: http.StatusForbidden,
}
}
type Error struct {
Verb string
PublicReason string
PrivateReason error
StatusCode int
}
func (e *Error) Error() string {
return fmt.Sprintf("challenge: error when processing challenge: %s: %v", e.Verb, e.PrivateReason)
}
func (e *Error) Unwrap() error {
return e.PrivateReason
}