1
0
mirror of https://github.com/0rangebananaspy/authelia.git synced 2024-09-14 22:47:21 +07:00
authelia/internal/handlers/handler_reset_password_step2.go
James Elliott ce6bf74c8d
fix(server): incorrect remote ip logged in error handler ()
This fixes edge cases where the remote IP was not correctly logged. Generally this is not an issue as most errors do not hit this handler, but in instances where a transport error occurs this is important.
2022-04-08 14:13:47 +10:00

130 lines
3.2 KiB
Go

package handlers
import (
"bytes"
"fmt"
"github.com/authelia/authelia/v4/internal/middlewares"
"github.com/authelia/authelia/v4/internal/templates"
"github.com/authelia/authelia/v4/internal/utils"
)
// ResetPasswordPOST handler for resetting passwords.
func ResetPasswordPOST(ctx *middlewares.AutheliaCtx) {
userSession := ctx.GetSession()
// Those checks unsure that the identity verification process has been initiated and completed successfully
// otherwise PasswordReset would not be set to true. We can improve the security of this check by making the
// request expire at some point because here it only expires when the cookie expires.
if userSession.PasswordResetUsername == nil {
ctx.Error(fmt.Errorf("no identity verification process has been initiated"), messageUnableToResetPassword)
return
}
username := *userSession.PasswordResetUsername
var requestBody resetPasswordStep2RequestBody
err := ctx.ParseBody(&requestBody)
if err != nil {
ctx.Error(err, messageUnableToResetPassword)
return
}
if err = ctx.Providers.PasswordPolicy.Check(requestBody.Password); err != nil {
ctx.Error(err, messagePasswordWeak)
return
}
err = ctx.Providers.UserProvider.UpdatePassword(username, requestBody.Password)
if err != nil {
switch {
case utils.IsStringInSliceContains(err.Error(), ldapPasswordComplexityCodes),
utils.IsStringInSliceContains(err.Error(), ldapPasswordComplexityErrors):
ctx.Error(err, ldapPasswordComplexityCode)
default:
ctx.Error(err, messageUnableToResetPassword)
}
return
}
ctx.Logger.Debugf("Password of user %s has been reset", username)
// Reset the request.
userSession.PasswordResetUsername = nil
err = ctx.SaveSession(userSession)
if err != nil {
ctx.Error(fmt.Errorf("unable to update password reset state: %s", err), messageOperationFailed)
return
}
// Send Notification.
userInfo, err := ctx.Providers.UserProvider.GetDetails(username)
if err != nil {
ctx.Logger.Error(err)
ctx.ReplyOK()
return
}
if len(userInfo.Emails) == 0 {
ctx.Logger.Error(fmt.Errorf("user %s has no email address configured", username))
ctx.ReplyOK()
return
}
bufHTML := new(bytes.Buffer)
disableHTML := false
if ctx.Configuration.Notifier != nil && ctx.Configuration.Notifier.SMTP != nil {
disableHTML = ctx.Configuration.Notifier.SMTP.DisableHTMLEmails
}
if !disableHTML {
htmlParams := map[string]interface{}{
"Title": "Password changed successfully",
"DisplayName": userInfo.DisplayName,
"RemoteIP": ctx.RemoteIP().String(),
}
err = templates.EmailPasswordResetHTML.Execute(bufHTML, htmlParams)
if err != nil {
ctx.Logger.Error(err)
ctx.ReplyOK()
return
}
}
bufText := new(bytes.Buffer)
textParams := map[string]interface{}{
"DisplayName": userInfo.DisplayName,
}
err = templates.EmailPasswordResetPlainText.Execute(bufText, textParams)
if err != nil {
ctx.Logger.Error(err)
ctx.ReplyOK()
return
}
ctx.Logger.Debugf("Sending an email to user %s (%s) to inform that the password has changed.",
username, userInfo.Emails[0])
err = ctx.Providers.Notifier.Send(userInfo.Emails[0], "Password changed successfully", bufText.String(), bufHTML.String())
if err != nil {
ctx.Logger.Error(err)
ctx.ReplyOK()
return
}
}