Skip to content

Commit

Permalink
Merge pull request #546 from openziti/self-service-password
Browse files Browse the repository at this point in the history
Password change feature (#148) Refactoring and fortification of token regeneration (#191)
  • Loading branch information
michaelquigley authored Feb 16, 2024
2 parents fb66f6e + 471cc49 commit 778e50c
Show file tree
Hide file tree
Showing 26 changed files with 1,792 additions and 129 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## v0.4.25

FEATURE: New action in the web console that allows changing the password of the logged-in account (https://github.com/openziti/zrok/issues/148)

FEATURE: The web console now supports revoking your current account token and generating a new one (https://github.com/openziti/zrok/issues/191)

CHANGE: When specifying OAuth configuration for public shares from the `zrok share public` or `zrok reserve` public commands, the flags and functionality for restricting the allowed email addresses of the authenticating users has changed. The old flag was `--oauth-email-domains`, which took a string value that needed to be contained in the user's email address. The new flag is `--oauth-email-address-patterns`, which accepts a glob-style filter, using https://github.com/gobwas/glob (https://github.com/openziti/zrok/issues/413)
Expand Down
75 changes: 75 additions & 0 deletions controller/changePassword.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package controller

import (
"github.com/go-openapi/runtime/middleware"
"github.com/openziti/zrok/controller/config"
"github.com/openziti/zrok/rest_model_zrok"
"github.com/openziti/zrok/rest_server_zrok/operations/account"
"github.com/sirupsen/logrus"
)

type changePasswordHandler struct {
cfg *config.Config
}

func newChangePasswordHandler(cfg *config.Config) *changePasswordHandler {
return &changePasswordHandler{
cfg: cfg,
}
}

func (handler *changePasswordHandler) Handle(params account.ChangePasswordParams, principal *rest_model_zrok.Principal) middleware.Responder {
if params.Body == nil || params.Body.Email == "" || params.Body.OldPassword == "" || params.Body.NewPassword == "" {
logrus.Error("missing email, old, or new password")
return account.NewChangePasswordUnauthorized()
}
logrus.Infof("received change password request for email '%v'", params.Body.Email)

tx, err := str.Begin()
if err != nil {
logrus.Errorf("error starting transaction: %v", err)
return account.NewChangePasswordUnauthorized()
}
defer func() { _ = tx.Rollback() }()

a, err := str.FindAccountWithEmail(params.Body.Email, tx)
if err != nil {
logrus.Errorf("error finding account '%v': %v", params.Body.Email, err)
return account.NewChangePasswordUnauthorized()
}
ohpwd, err := rehashPassword(params.Body.OldPassword, a.Salt)
if err != nil {
logrus.Errorf("error hashing password for '%v': %v", params.Body.Email, err)
return account.NewChangePasswordUnauthorized()
}
if a.Password != ohpwd.Password {
logrus.Errorf("password mismatch for account '%v'", params.Body.Email)
return account.NewChangePasswordUnauthorized()
}

if err := validatePassword(handler.cfg, params.Body.NewPassword); err != nil {
logrus.Errorf("password not valid for request '%v': %v", a.Email, err)
return account.NewChangePasswordUnprocessableEntity().WithPayload(rest_model_zrok.ErrorMessage(err.Error()))
}

nhpwd, err := HashPassword(params.Body.NewPassword)
if err != nil {
logrus.Errorf("error hashing password for '%v': %v", a.Email, err)
return account.NewChangePasswordInternalServerError()
}
a.Salt = nhpwd.Salt
a.Password = nhpwd.Password

if _, err := str.UpdateAccount(a, tx); err != nil {
logrus.Errorf("error updating for '%v': %v", a.Email, err)
return account.NewChangePasswordInternalServerError()
}

if err := tx.Commit(); err != nil {
logrus.Errorf("error committing '%v': %v", a.Email, err)
return account.NewChangePasswordInternalServerError()
}

logrus.Infof("change password for '%v'", a.Email)
return account.NewChangePasswordOK()
}
1 change: 1 addition & 0 deletions controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func Run(inCfg *config.Config) error {

api := operations.NewZrokAPI(swaggerSpec)
api.KeyAuth = newZrokAuthenticator(cfg).authenticate
api.AccountChangePasswordHandler = newChangePasswordHandler(cfg)
api.AccountInviteHandler = newInviteHandler(cfg)
api.AccountLoginHandler = account.LoginHandlerFunc(loginHandler)
api.AccountRegisterHandler = newRegisterHandler(cfg)
Expand Down
9 changes: 5 additions & 4 deletions controller/resetToken.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ func newResetTokenHandler() *resetTokenHandler {
}

func (handler *resetTokenHandler) Handle(params account.ResetTokenParams, principal *rest_model_zrok.Principal) middleware.Responder {
if params.Body.EmailAddress == "" {
logrus.Error("missing email")
logrus.Infof("received token regeneration request for email '%v'", principal.Email)

if params.Body.EmailAddress != principal.Email {
logrus.Errorf("mismatched account '%v' for '%v'", params.Body.EmailAddress, principal.Email)
return account.NewResetTokenNotFound()
}
logrus.Infof("received token reset request for email '%v'", params.Body.EmailAddress)

tx, err := str.Begin()
if err != nil {
Expand Down Expand Up @@ -56,7 +57,7 @@ func (handler *resetTokenHandler) Handle(params account.ResetTokenParams, princi
return account.NewResetTokenInternalServerError()
}

logrus.Infof("reset token for '%v'", a.Email)
logrus.Infof("regenerated token '%v' for '%v'", a.Token, a.Email)

return account.NewResetTokenOK().WithPayload(&account.ResetTokenOKBody{Token: token})
}
41 changes: 41 additions & 0 deletions rest_client_zrok/account/account_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

150 changes: 150 additions & 0 deletions rest_client_zrok/account/change_password_parameters.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 778e50c

Please sign in to comment.