Add endpoint to disable totp auth
This commit is contained in:
parent
87d0c9088d
commit
895d9613b5
4 changed files with 67 additions and 4 deletions
|
@ -93,6 +93,52 @@ func UserTOTPEnable(c echo.Context) error {
|
||||||
return c.JSON(http.StatusOK, models.Message{Message: "TOTP was enabled successfully."})
|
return c.JSON(http.StatusOK, models.Message{Message: "TOTP was enabled successfully."})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UserTOTPDisable disables totp settings for the current user.
|
||||||
|
// @Summary Disable totp settings
|
||||||
|
// @Description Disables any totp settings for the current user.
|
||||||
|
// @tags user
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Security JWTKeyAuth
|
||||||
|
// @Param totp body user.Login true "The current user's password (only password is enough)."
|
||||||
|
// @Success 200 {object} models.Message "Successfully disabled"
|
||||||
|
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Something's invalid."
|
||||||
|
// @Failure 404 {object} code.vikunja.io/web.HTTPError "User does not exist."
|
||||||
|
// @Failure 500 {object} models.Message "Internal server error."
|
||||||
|
// @Router /user/settings/totp/disable [post]
|
||||||
|
func UserTOTPDisable(c echo.Context) error {
|
||||||
|
login := &user.Login{}
|
||||||
|
if err := c.Bind(login); err != nil {
|
||||||
|
log.Debugf("Invalid model error. Internal error was: %s", err.Error())
|
||||||
|
if he, is := err.(*echo.HTTPError); is {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid model provided. Error was: %s", he.Message))
|
||||||
|
}
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid model provided."))
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := user.GetCurrentUser(c)
|
||||||
|
if err != nil {
|
||||||
|
return handler.HandleHTTPError(err, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err = user.GetUserByID(u.ID)
|
||||||
|
if err != nil {
|
||||||
|
return handler.HandleHTTPError(err, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = user.CheckUserPassword(u, login.Password)
|
||||||
|
if err != nil {
|
||||||
|
return handler.HandleHTTPError(err, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = user.DisableTOTP(u)
|
||||||
|
if err != nil {
|
||||||
|
return handler.HandleHTTPError(err, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(http.StatusOK, models.Message{Message: "TOTP was enabled successfully."})
|
||||||
|
}
|
||||||
|
|
||||||
// UserTOTPQrCode is the handler to show a qr code to enroll the user into totp
|
// UserTOTPQrCode is the handler to show a qr code to enroll the user into totp
|
||||||
// @Summary Totp QR Code
|
// @Summary Totp QR Code
|
||||||
// @Description Returns a qr code for easier setup at end user's devices.
|
// @Description Returns a qr code for easier setup at end user's devices.
|
||||||
|
|
|
@ -212,6 +212,7 @@ func registerAPIRoutes(a *echo.Group) {
|
||||||
u.GET("/settings/totp", apiv1.UserTOTP)
|
u.GET("/settings/totp", apiv1.UserTOTP)
|
||||||
u.POST("/settings/totp/enroll", apiv1.UserTOTPEnroll)
|
u.POST("/settings/totp/enroll", apiv1.UserTOTPEnroll)
|
||||||
u.POST("/settings/totp/enable", apiv1.UserTOTPEnable)
|
u.POST("/settings/totp/enable", apiv1.UserTOTPEnable)
|
||||||
|
u.POST("/settings/totp/disable", apiv1.UserTOTPDisable)
|
||||||
u.GET("/settings/totp/qrcode", apiv1.UserTOTPQrCode)
|
u.GET("/settings/totp/qrcode", apiv1.UserTOTPQrCode)
|
||||||
|
|
||||||
listHandler := &handler.WebHandler{
|
listHandler := &handler.WebHandler{
|
||||||
|
|
|
@ -105,6 +105,12 @@ func EnableTOTP(passcode *TOTPPasscode) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DisableTOTP removes all totp settings for a user.
|
||||||
|
func DisableTOTP(user *User) (err error) {
|
||||||
|
_, err = x.Where("user_id = ?", user.ID).Delete(&TOTP{})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// ValidateTOTPPasscode validated totp codes of users.
|
// ValidateTOTPPasscode validated totp codes of users.
|
||||||
func ValidateTOTPPasscode(passcode *TOTPPasscode) (t *TOTP, err error) {
|
func ValidateTOTPPasscode(passcode *TOTPPasscode) (t *TOTP, err error) {
|
||||||
t, err = GetTOTPForUser(passcode.User)
|
t, err = GetTOTPForUser(passcode.User)
|
||||||
|
|
|
@ -172,17 +172,27 @@ func CheckUserCredentials(u *Login) (*User, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the users password
|
// Check the users password
|
||||||
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(u.Password))
|
err = CheckUserPassword(user, u.Password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == bcrypt.ErrMismatchedHashAndPassword {
|
|
||||||
return &User{}, ErrWrongUsernameOrPassword{}
|
|
||||||
}
|
|
||||||
return &User{}, err
|
return &User{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckUserPassword checks and verifies a user's password. The user object needs to contain the hashed password from the database.
|
||||||
|
func CheckUserPassword(user *User, password string) error {
|
||||||
|
err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
|
||||||
|
if err != nil {
|
||||||
|
if err == bcrypt.ErrMismatchedHashAndPassword {
|
||||||
|
return ErrWrongUsernameOrPassword{}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetCurrentUser returns the current user based on its jwt token
|
// GetCurrentUser returns the current user based on its jwt token
|
||||||
func GetCurrentUser(c echo.Context) (user *User, err error) {
|
func GetCurrentUser(c echo.Context) (user *User, err error) {
|
||||||
jwtinf := c.Get("user").(*jwt.Token)
|
jwtinf := c.Get("user").(*jwt.Token)
|
||||||
|
|
Loading…
Reference in a new issue