Commit 63a16ea5 authored by ale's avatar ale
Browse files

Kick out other sessions on password changes

Makes it easier to recover compromised accounts by automatically
kicking out other logged in sessions from the account management
application whenever a password change (either active or via recovery)
happens.
parent 2dbf9139
Pipeline #419 passed with stages
in 1 minute and 17 seconds
......@@ -140,6 +140,16 @@ func (u *User) SetPassword(password string) error {
return nil
}
// PasswordSnippet returns a chunk of the encrypted password that can
// be used to detect password changes without revealing sufficient
// information about the encrypted password itself.
func (u *User) PasswordSnippet() string {
if len(u.EncryptedPassword) < 6 {
return ""
}
return u.EncryptedPassword[len(u.EncryptedPassword)-6:]
}
// Change password.
var minPasswordLength = 6
......
......@@ -334,6 +334,7 @@ func (s *Service) successfulLogin(w http.ResponseWriter, r *http.Request, userna
}
as.Authenticated = true
as.Username = username
as.PwToken = user.PasswordSnippet()
s.deleteLoginSession(r)
if err := sessions.Save(r, w); err != nil {
......
......@@ -5,6 +5,7 @@ import (
log "github.com/Sirupsen/logrus"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
"git.autistici.org/ale/idp"
"git.autistici.org/ale/idp/web"
......@@ -64,6 +65,19 @@ func (s *Service) withUser(f func(http.ResponseWriter, *http.Request, idp.Txn, *
if err != nil {
return err
}
// With the following check, when a password
// change happens (either actively, or through
// recovery), we kick out from the account
// management service every other session that
// might be still logged in.
if as.PwToken != user.PasswordSnippet() {
s.DeleteAuthSession(r)
sessions.Save(r, w)
http.Redirect(w, r, "/account/login", http.StatusFound)
return nil
}
return f(w, r, txn, user)
}); err != nil {
log.WithFields(log.Fields{
......@@ -154,10 +168,17 @@ func (s *Service) handlePasswordChange(w http.ResponseWriter, r *http.Request, t
if err := txn.Commit(); err != nil {
return err
}
// Reset the PwToken in the current session. All other active
// sessions will be logged out.
as, _ := s.GetAuthSession(r)
as.PwToken = user.PasswordSnippet()
s.Flash(r, "Password changed successfully.")
http.Redirect(w, r, "/account/overview", http.StatusFound)
return nil
}
s.RenderTemplate(w, r, "account_pwchange.html", tplCtx)
return nil
}
......
......@@ -146,6 +146,7 @@ func (s *Service) DeleteSession(r *http.Request, name string) {
type AuthSession struct {
Authenticated bool
Username string
PwToken string
}
const (
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment