feat: Add option to use HS512 secret for JWT instead of ED25519 (#680)
* Add functionality for HS512 JWT tokens * Add HS512_SECRET to installation docs * Update CHANGELOG.md regarding HS512 * Move HS512_SECRET to advenced section in docs * Move token Keyfunc logic to Server function * Add Keyfunc to spelling * chore: spelling Signed-off-by: Xe Iaso <me@xeiaso.net> --------- Signed-off-by: Xe Iaso <me@xeiaso.net> Co-authored-by: Martin Weidenauer <mweidenauer@nanx0as46153.anx.local> Co-authored-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
parent
1562f88c35
commit
59f5b07281
7 changed files with 68 additions and 36 deletions
|
|
@ -63,19 +63,37 @@ var (
|
|||
)
|
||||
|
||||
type Server struct {
|
||||
next http.Handler
|
||||
mux *http.ServeMux
|
||||
policy *policy.ParsedConfig
|
||||
DNSBLCache *decaymap.Impl[string, dnsbl.DroneBLResponse]
|
||||
OGTags *ogtags.OGTagCache
|
||||
cookieName string
|
||||
priv ed25519.PrivateKey
|
||||
pub ed25519.PublicKey
|
||||
opts Options
|
||||
next http.Handler
|
||||
mux *http.ServeMux
|
||||
policy *policy.ParsedConfig
|
||||
DNSBLCache *decaymap.Impl[string, dnsbl.DroneBLResponse]
|
||||
OGTags *ogtags.OGTagCache
|
||||
cookieName string
|
||||
ed25519Priv ed25519.PrivateKey
|
||||
hs512Secret []byte
|
||||
opts Options
|
||||
}
|
||||
|
||||
func (s *Server) getTokenKeyfunc() jwt.Keyfunc {
|
||||
// return ED25519 key if HS512 is not set
|
||||
if len(s.hs512Secret) == 0 {
|
||||
return func(token *jwt.Token) (interface{}, error) {
|
||||
return s.ed25519Priv.Public().(ed25519.PublicKey), nil
|
||||
}
|
||||
} else {
|
||||
return func(token *jwt.Token) (interface{}, error) {
|
||||
return s.hs512Secret, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) challengeFor(r *http.Request, difficulty int) string {
|
||||
fp := sha256.Sum256(s.pub[:])
|
||||
var fp [32]byte
|
||||
if len(s.hs512Secret) == 0 {
|
||||
fp = sha256.Sum256(s.ed25519Priv.Public().(ed25519.PublicKey)[:])
|
||||
} else {
|
||||
fp = sha256.Sum256(s.hs512Secret)
|
||||
}
|
||||
|
||||
challengeData := fmt.Sprintf(
|
||||
"X-Real-IP=%s,User-Agent=%s,WeekTime=%s,Fingerprint=%x,Difficulty=%d",
|
||||
|
|
@ -149,9 +167,7 @@ func (s *Server) maybeReverseProxy(w http.ResponseWriter, r *http.Request, httpS
|
|||
return
|
||||
}
|
||||
|
||||
token, err := jwt.ParseWithClaims(ckie.Value, jwt.MapClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return s.pub, nil
|
||||
}, jwt.WithExpirationRequired(), jwt.WithStrictDecoding())
|
||||
token, err := jwt.ParseWithClaims(ckie.Value, jwt.MapClaims{}, s.getTokenKeyfunc(), jwt.WithExpirationRequired(), jwt.WithStrictDecoding())
|
||||
|
||||
if err != nil || !token.Valid {
|
||||
lg.Debug("invalid token", "path", r.URL.Path, "err", err)
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ type Options struct {
|
|||
BasePrefix string
|
||||
WebmasterEmail string
|
||||
RedirectDomains []string
|
||||
PrivateKey ed25519.PrivateKey
|
||||
ED25519PrivateKey ed25519.PrivateKey
|
||||
HS512Secret []byte
|
||||
CookieExpiration time.Duration
|
||||
StripBasePrefix bool
|
||||
OpenGraph config.OpenGraph
|
||||
|
|
@ -88,13 +89,13 @@ func LoadPoliciesOrDefault(ctx context.Context, fname string, defaultDifficulty
|
|||
}
|
||||
|
||||
func New(opts Options) (*Server, error) {
|
||||
if opts.PrivateKey == nil {
|
||||
if opts.ED25519PrivateKey == nil && opts.HS512Secret == nil {
|
||||
slog.Debug("opts.PrivateKey not set, generating a new one")
|
||||
_, priv, err := ed25519.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("lib: can't generate private key: %v", err)
|
||||
}
|
||||
opts.PrivateKey = priv
|
||||
opts.ED25519PrivateKey = priv
|
||||
}
|
||||
|
||||
anubis.BasePrefix = opts.BasePrefix
|
||||
|
|
@ -106,14 +107,14 @@ func New(opts Options) (*Server, error) {
|
|||
}
|
||||
|
||||
result := &Server{
|
||||
next: opts.Next,
|
||||
priv: opts.PrivateKey,
|
||||
pub: opts.PrivateKey.Public().(ed25519.PublicKey),
|
||||
policy: opts.Policy,
|
||||
opts: opts,
|
||||
DNSBLCache: decaymap.New[string, dnsbl.DroneBLResponse](),
|
||||
OGTags: ogtags.NewOGTagCache(opts.Target, opts.Policy.OpenGraph),
|
||||
cookieName: cookieName,
|
||||
next: opts.Next,
|
||||
ed25519Priv: opts.ED25519PrivateKey,
|
||||
hs512Secret: opts.HS512Secret,
|
||||
policy: opts.Policy,
|
||||
opts: opts,
|
||||
DNSBLCache: decaymap.New[string, dnsbl.DroneBLResponse](),
|
||||
OGTags: ogtags.NewOGTagCache(opts.Target, opts.Policy.OpenGraph),
|
||||
cookieName: cookieName,
|
||||
}
|
||||
|
||||
mux := http.NewServeMux()
|
||||
|
|
|
|||
|
|
@ -201,5 +201,9 @@ func (s *Server) signJWT(claims jwt.MapClaims) (string, error) {
|
|||
claims["nbf"] = time.Now().Add(-1 * time.Minute).Unix()
|
||||
claims["exp"] = time.Now().Add(s.opts.CookieExpiration).Unix()
|
||||
|
||||
return jwt.NewWithClaims(jwt.SigningMethodEdDSA, claims).SignedString(s.priv)
|
||||
if len(s.hs512Secret) == 0 {
|
||||
return jwt.NewWithClaims(jwt.SigningMethodEdDSA, claims).SignedString(s.ed25519Priv)
|
||||
} else {
|
||||
return jwt.NewWithClaims(jwt.SigningMethodHS512, claims).SignedString(s.hs512Secret)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue