Add endpoint to disable totp auth

This commit is contained in:
kolaente 2020-04-18 01:38:49 +02:00
parent 87d0c9088d
commit 895d9613b5
No known key found for this signature in database
GPG key ID: F40E70337AB24C9B
4 changed files with 67 additions and 4 deletions

View file

@ -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.

View file

@ -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{

View file

@ -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)

View file

@ -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)