Issue Details
I was just writing an authentication plugin for a method of authentication with the property that all requests are authenticated (ie matched to users), but only some are authorized. The actual authentication plugin is working great, but while attempting to serve a custom error page that displayed the user's name, I discovered that the http.auth.user.id placeholder (and custom placeholders derived from user metadata) aren't set if an Authenticator returns false for the second parameter.
I'd like Caddy to set these http.auth.user.* properties before returning HTTP 401, which will allow reading these if present in an error handler. I think this would be achieved by reordering some lines in the following function:
|
func (a Authentication) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error { |
|
repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer) |
|
var user User |
|
var authed bool |
|
var err error |
|
for provName, prov := range a.Providers { |
|
user, authed, err = prov.Authenticate(w, r) |
|
if err != nil { |
|
if c := a.logger.Check(zapcore.ErrorLevel, "auth provider returned error"); c != nil { |
|
c.Write(zap.String("provider", provName), zap.Error(err)) |
|
} |
|
// Set the error from the authentication provider in a placeholder, |
|
// so it can be used in the handle_errors directive. |
|
repl.Set("http.auth."+provName+".error", err.Error()) |
|
continue |
|
} |
|
if authed { |
|
break |
|
} |
|
} |
|
if !authed { |
|
return caddyhttp.Error(http.StatusUnauthorized, fmt.Errorf("not authenticated")) |
|
} |
|
|
|
repl.Set("http.auth.user.id", user.ID) |
|
for k, v := range user.Metadata { |
|
repl.Set("http.auth.user."+k, v) |
|
} |
|
|
|
return next.ServeHTTP(w, r) |
|
} |
Specifically, the following block:
repl.Set("http.auth.user.id", user.ID)
for k, v := range user.Metadata {
repl.Set("http.auth.user."+k, v)
}
should move between the for loop and the if !authed block (and perhaps be wrapped in a check to ensure user.ID != "").
I believe this is a fully backwards-compatible change, since we'd simply be setting extra placeholders in the unauthorized case.
Assistance Disclosure
AI not used
If AI was used, describe the extent to which it was used.
No response
Issue Details
I was just writing an authentication plugin for a method of authentication with the property that all requests are authenticated (ie matched to users), but only some are authorized. The actual authentication plugin is working great, but while attempting to serve a custom error page that displayed the user's name, I discovered that the
http.auth.user.idplaceholder (and custom placeholders derived from user metadata) aren't set if anAuthenticatorreturns false for the second parameter.I'd like Caddy to set these
http.auth.user.*properties before returning HTTP 401, which will allow reading these if present in an error handler. I think this would be achieved by reordering some lines in the following function:caddy/modules/caddyhttp/caddyauth/caddyauth.go
Lines 78 to 108 in ef496e5
Specifically, the following block:
should move between the for loop and the
if !authedblock (and perhaps be wrapped in a check to ensureuser.ID != "").I believe this is a fully backwards-compatible change, since we'd simply be setting extra placeholders in the unauthorized case.
Assistance Disclosure
AI not used
If AI was used, describe the extent to which it was used.
No response