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