mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-04 13:28:25 +00:00 
			
		
		
		
	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:
		
				
					committed by
					
						
						Lunny Xiao
					
				
			
			
				
	
			
			
			
						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
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user