fix: /login throttles failed logins per client address behind trusted proxies (surf.ClientIP), like /register
Behind a reverse proxy every visitor had the proxy's RemoteAddr, so one client's failed logins locked the account for all. The throttle key is now surf.ClientIP with http.trusted_proxies, the expression /register uses; X-Forwarded-For from an untrusted peer is still ignored. RemoteIP is unchanged.
This commit is contained in:
@@ -54,7 +54,9 @@ const invalidLoginBody = "Invalid email or password"
|
||||
// as a wrong password and counts as a failed attempt for the throttle; an
|
||||
// account that is also deactivated is refused before the restore, so it
|
||||
// stays deactivated and gets no mail. With the key off such an account signs
|
||||
// in as before. Activation gates login, deactivation does not.
|
||||
// in as before. Activation gates login, deactivation does not. The throttle
|
||||
// counts failed attempts per user and client address, which is
|
||||
// surf.ClientIP with http.trusted_proxies, as for /register.
|
||||
func Login(app *backpack.App) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
gdb, secret, ok := sessionDeps(w, app)
|
||||
@@ -74,7 +76,7 @@ func Login(app *backpack.App) http.HandlerFunc {
|
||||
writeOpaque500(w)
|
||||
return
|
||||
}
|
||||
ip := remoteIP(r)
|
||||
ip := surf.ClientIP(r, surf.TrustedProxies(appConfig(app)))
|
||||
if user != nil {
|
||||
if err := classes.RejectIfThrottled(ctx, gdb, user, ip); err != nil {
|
||||
if classes.IsLoginRejected(err) {
|
||||
@@ -1159,9 +1161,10 @@ func requestURL(r *http.Request) string {
|
||||
return scheme + "://" + r.Host + r.URL.Path
|
||||
}
|
||||
|
||||
// RemoteIP returns the host part of r.RemoteAddr, the address /login uses
|
||||
// for its throttle (r.RemoteAddr itself when it has no port, "" when it is
|
||||
// empty). /register records surf.ClientIP with the trusted proxies instead.
|
||||
// RemoteIP returns the host part of r.RemoteAddr (r.RemoteAddr itself when
|
||||
// it has no port, "" when it is empty), with no proxy handling. /login and
|
||||
// /register key their throttles on surf.ClientIP with the trusted proxies;
|
||||
// RemoteIP stays for callers that want the connection address.
|
||||
func RemoteIP(r *http.Request) string {
|
||||
return remoteIP(r)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user