Only allow token authentication with 2FA enabled (#2184)
* Don't allow for plain username/password authentication when 2FA is enabled * Removed debugging statement * Don't assume a token belongs to a given user, handle two-factor errors properly * Simplified user/token matching, refactored error handling for two-factor authentication * Change authentication response to avoid bruteforcing * Add TODO item as a comment for changing the response for security purposes
This commit is contained in:
parent
1d032f5220
commit
7e12aac61c
|
@ -156,24 +156,50 @@ func HTTP(ctx *context.Context) {
|
||||||
ctx.Handle(http.StatusInternalServerError, "UserSignIn error: %v", err)
|
ctx.Handle(http.StatusInternalServerError, "UserSignIn error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Assume username now is a token.
|
if authUser == nil {
|
||||||
token, err := models.GetAccessTokenBySHA(authUsername)
|
authUser, err = models.GetUserByName(authUsername)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrUserNotExist(err) {
|
||||||
|
ctx.HandleText(http.StatusUnauthorized, "invalid credentials")
|
||||||
|
} else {
|
||||||
|
ctx.Handle(http.StatusInternalServerError, "GetUserByName", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assume password is a token.
|
||||||
|
token, err := models.GetAccessTokenBySHA(authPasswd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrAccessTokenNotExist(err) || models.IsErrAccessTokenEmpty(err) {
|
if models.IsErrAccessTokenNotExist(err) || models.IsErrAccessTokenEmpty(err) {
|
||||||
ctx.HandleText(http.StatusUnauthorized, "invalid token")
|
ctx.HandleText(http.StatusUnauthorized, "invalid credentials")
|
||||||
} else {
|
} else {
|
||||||
ctx.Handle(http.StatusInternalServerError, "GetAccessTokenBySha", err)
|
ctx.Handle(http.StatusInternalServerError, "GetAccessTokenBySha", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if authUser.ID != token.UID {
|
||||||
|
ctx.HandleText(http.StatusUnauthorized, "invalid credentials")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
token.Updated = time.Now()
|
token.Updated = time.Now()
|
||||||
if err = models.UpdateAccessToken(token); err != nil {
|
if err = models.UpdateAccessToken(token); err != nil {
|
||||||
ctx.Handle(http.StatusInternalServerError, "UpdateAccessToken", err)
|
ctx.Handle(http.StatusInternalServerError, "UpdateAccessToken", err)
|
||||||
}
|
}
|
||||||
authUser, err = models.GetUserByID(token.UID)
|
|
||||||
if err != nil {
|
} else {
|
||||||
ctx.Handle(http.StatusInternalServerError, "GetUserByID", err)
|
_, err = models.GetTwoFactorByUID(authUser.ID)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
// TODO: This response should be changed to "invalid credentials" for security reasons once the expectation behind it (creating an app token to authenticate) is properly documented
|
||||||
|
ctx.HandleText(http.StatusUnauthorized, "Users with two-factor authentication enabled cannot perform HTTP/HTTPS operations via plain username and password. Please create and use a personal access token on the user settings page")
|
||||||
|
return
|
||||||
|
} else if !models.IsErrTwoFactorNotEnrolled(err) {
|
||||||
|
ctx.Handle(http.StatusInternalServerError, "IsErrTwoFactorNotEnrolled", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue