feat(lib): Add optional restrictions for JWT based on a specific header value (#697)
* Add JWTRestrictionHeader funktionality * Add JWTRestrictionHeader to docs * Move JWT_RESTRICTION_HEADER from advanced section to normal one * Add rull request URL to Changelog * Set default value of JWT_RESTRICTION_HEADER to X-Real-IP
This commit is contained in:
parent
83503525f2
commit
ff691dfee8
5 changed files with 79 additions and 46 deletions
|
|
@ -237,6 +237,13 @@ func (s *Server) maybeReverseProxy(w http.ResponseWriter, r *http.Request, httpS
|
|||
return
|
||||
}
|
||||
|
||||
if s.opts.JWTRestrictionHeader != "" && claims["restriction"] != internal.SHA256sum(r.Header.Get(s.opts.JWTRestrictionHeader)) {
|
||||
lg.Debug("JWT restriction header is invalid")
|
||||
s.ClearCookie(w, CookieOpts{Path: cookiePath, Host: r.Host})
|
||||
s.RenderIndex(w, r, cr, rule, httpStatusOnly)
|
||||
return
|
||||
}
|
||||
|
||||
r.Header.Add("X-Anubis-Status", "PASS")
|
||||
s.ServeHTTPNext(w, r)
|
||||
}
|
||||
|
|
@ -484,12 +491,33 @@ func (s *Server) PassChallenge(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// generate JWT cookie
|
||||
tokenString, err := s.signJWT(jwt.MapClaims{
|
||||
"challenge": chall.ID,
|
||||
"method": rule.Challenge.Algorithm,
|
||||
"policyRule": rule.Hash(),
|
||||
"action": string(cr.Rule),
|
||||
})
|
||||
var tokenString string
|
||||
|
||||
// check if JWTRestrictionHeader is set and header is in request
|
||||
if s.opts.JWTRestrictionHeader != "" {
|
||||
if r.Header.Get(s.opts.JWTRestrictionHeader) == "" {
|
||||
lg.Error("JWTRestrictionHeader is set in config but not found in request, please check your reverse proxy config.")
|
||||
s.ClearCookie(w, CookieOpts{Path: cookiePath, Host: r.Host})
|
||||
s.respondWithError(w, r, "failed to sign JWT")
|
||||
return
|
||||
} else {
|
||||
tokenString, err = s.signJWT(jwt.MapClaims{
|
||||
"challenge": chall.ID,
|
||||
"method": rule.Challenge.Algorithm,
|
||||
"policyRule": rule.Hash(),
|
||||
"action": string(cr.Rule),
|
||||
"restriction": internal.SHA256sum(r.Header.Get(s.opts.JWTRestrictionHeader)),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
tokenString, err = s.signJWT(jwt.MapClaims{
|
||||
"challenge": chall.ID,
|
||||
"method": rule.Challenge.Algorithm,
|
||||
"policyRule": rule.Hash(),
|
||||
"action": string(cr.Rule),
|
||||
})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
lg.Error("failed to sign JWT", "err", err)
|
||||
s.ClearCookie(w, CookieOpts{Path: cookiePath, Host: r.Host})
|
||||
|
|
|
|||
|
|
@ -27,24 +27,25 @@ import (
|
|||
)
|
||||
|
||||
type Options struct {
|
||||
Next http.Handler
|
||||
Policy *policy.ParsedConfig
|
||||
Target string
|
||||
CookieDynamicDomain bool
|
||||
CookieDomain string
|
||||
CookieExpiration time.Duration
|
||||
CookiePartitioned bool
|
||||
BasePrefix string
|
||||
WebmasterEmail string
|
||||
RedirectDomains []string
|
||||
ED25519PrivateKey ed25519.PrivateKey
|
||||
HS512Secret []byte
|
||||
StripBasePrefix bool
|
||||
OpenGraph config.OpenGraph
|
||||
ServeRobotsTXT bool
|
||||
CookieSecure bool
|
||||
Logger *slog.Logger
|
||||
PublicUrl string
|
||||
Next http.Handler
|
||||
Policy *policy.ParsedConfig
|
||||
Target string
|
||||
CookieDynamicDomain bool
|
||||
CookieDomain string
|
||||
CookieExpiration time.Duration
|
||||
CookiePartitioned bool
|
||||
BasePrefix string
|
||||
WebmasterEmail string
|
||||
RedirectDomains []string
|
||||
ED25519PrivateKey ed25519.PrivateKey
|
||||
HS512Secret []byte
|
||||
StripBasePrefix bool
|
||||
OpenGraph config.OpenGraph
|
||||
ServeRobotsTXT bool
|
||||
CookieSecure bool
|
||||
Logger *slog.Logger
|
||||
PublicUrl string
|
||||
JWTRestrictionHeader string
|
||||
}
|
||||
|
||||
func LoadPoliciesOrDefault(ctx context.Context, fname string, defaultDifficulty int) (*policy.ParsedConfig, error) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue