In basic auth check for tokens before call UserSignIn (#5725)
* Check first if user/password is a token * In basic auth check if user/password is a token * Remove unnecessary else statement * Changes of fmt
This commit is contained in:
parent
48a9025346
commit
fc038caa69
2 changed files with 85 additions and 44 deletions
|
@ -135,15 +135,56 @@ func SignedInUser(ctx *macaron.Context, sess session.Store) (*models.User, bool)
|
||||||
if len(baHead) > 0 {
|
if len(baHead) > 0 {
|
||||||
auths := strings.Fields(baHead)
|
auths := strings.Fields(baHead)
|
||||||
if len(auths) == 2 && auths[0] == "Basic" {
|
if len(auths) == 2 && auths[0] == "Basic" {
|
||||||
|
var u *models.User
|
||||||
|
|
||||||
uname, passwd, _ := base.BasicAuthDecode(auths[1])
|
uname, passwd, _ := base.BasicAuthDecode(auths[1])
|
||||||
|
|
||||||
u, err := models.UserSignIn(uname, passwd)
|
// Check if username or password is a token
|
||||||
|
isUsernameToken := len(passwd) == 0 || passwd == "x-oauth-basic"
|
||||||
|
// Assume username is token
|
||||||
|
authToken := uname
|
||||||
|
if !isUsernameToken {
|
||||||
|
// Assume password is token
|
||||||
|
authToken = passwd
|
||||||
|
}
|
||||||
|
token, err := models.GetAccessTokenBySHA(authToken)
|
||||||
|
if err == nil {
|
||||||
|
if isUsernameToken {
|
||||||
|
u, err = models.GetUserByID(token.UID)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(4, "GetUserByID: %v", err)
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
u, err = models.GetUserByName(uname)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(4, "GetUserByID: %v", err)
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if u.ID != token.UID {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
token.UpdatedUnix = util.TimeStampNow()
|
||||||
|
if err = models.UpdateAccessToken(token); err != nil {
|
||||||
|
log.Error(4, "UpdateAccessToken: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !models.IsErrAccessTokenNotExist(err) && !models.IsErrAccessTokenEmpty(err) {
|
||||||
|
log.Error(4, "GetAccessTokenBySha: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if u == nil {
|
||||||
|
u, err = models.UserSignIn(uname, passwd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !models.IsErrUserNotExist(err) {
|
if !models.IsErrUserNotExist(err) {
|
||||||
log.Error(4, "UserSignIn: %v", err)
|
log.Error(4, "UserSignIn: %v", err)
|
||||||
}
|
}
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Data["IsApiToken"] = true
|
ctx.Data["IsApiToken"] = true
|
||||||
return u, true
|
return u, true
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,24 +143,24 @@ func HTTP(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
authUser, err = models.UserSignIn(authUsername, authPasswd)
|
// Check if username or password is a token
|
||||||
if err != nil {
|
|
||||||
if !models.IsErrUserNotExist(err) {
|
|
||||||
ctx.ServerError("UserSignIn error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if authUser == nil {
|
|
||||||
isUsernameToken := len(authPasswd) == 0 || authPasswd == "x-oauth-basic"
|
isUsernameToken := len(authPasswd) == 0 || authPasswd == "x-oauth-basic"
|
||||||
|
|
||||||
// Assume username is token
|
// Assume username is token
|
||||||
authToken := authUsername
|
authToken := authUsername
|
||||||
|
|
||||||
if !isUsernameToken {
|
if !isUsernameToken {
|
||||||
// Assume password is token
|
// Assume password is token
|
||||||
authToken = authPasswd
|
authToken = authPasswd
|
||||||
|
}
|
||||||
|
// Assume password is a token.
|
||||||
|
token, err := models.GetAccessTokenBySHA(authToken)
|
||||||
|
if err == nil {
|
||||||
|
if isUsernameToken {
|
||||||
|
authUser, err = models.GetUserByID(token.UID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("GetUserByID", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
authUser, err = models.GetUserByName(authUsername)
|
authUser, err = models.GetUserByName(authUsername)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrUserNotExist(err) {
|
if models.IsErrUserNotExist(err) {
|
||||||
|
@ -170,37 +170,37 @@ func HTTP(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
if authUser.ID != token.UID {
|
||||||
|
|
||||||
// Assume password is a token.
|
|
||||||
token, err := models.GetAccessTokenBySHA(authToken)
|
|
||||||
if err != nil {
|
|
||||||
if models.IsErrAccessTokenNotExist(err) || models.IsErrAccessTokenEmpty(err) {
|
|
||||||
ctx.HandleText(http.StatusUnauthorized, "invalid credentials")
|
|
||||||
} else {
|
|
||||||
ctx.ServerError("GetAccessTokenBySha", err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if isUsernameToken {
|
|
||||||
authUser, err = models.GetUserByID(token.UID)
|
|
||||||
if err != nil {
|
|
||||||
ctx.ServerError("GetUserByID", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else if authUser.ID != token.UID {
|
|
||||||
ctx.HandleText(http.StatusUnauthorized, "invalid credentials")
|
ctx.HandleText(http.StatusUnauthorized, "invalid credentials")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
token.UpdatedUnix = util.TimeStampNow()
|
token.UpdatedUnix = util.TimeStampNow()
|
||||||
if err = models.UpdateAccessToken(token); err != nil {
|
if err = models.UpdateAccessToken(token); err != nil {
|
||||||
ctx.ServerError("UpdateAccessToken", err)
|
ctx.ServerError("UpdateAccessToken", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_, err = models.GetTwoFactorByUID(authUser.ID)
|
if !models.IsErrAccessTokenNotExist(err) && !models.IsErrAccessTokenEmpty(err) {
|
||||||
|
log.Error(4, "GetAccessTokenBySha: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if authUser == nil {
|
||||||
|
// Check username and password
|
||||||
|
authUser, err = models.UserSignIn(authUsername, authPasswd)
|
||||||
|
if err != nil {
|
||||||
|
if !models.IsErrUserNotExist(err) {
|
||||||
|
ctx.ServerError("UserSignIn error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if authUser == nil {
|
||||||
|
ctx.HandleText(http.StatusUnauthorized, "invalid credentials")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = models.GetTwoFactorByUID(authUser.ID)
|
||||||
if err == nil {
|
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
|
// 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")
|
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")
|
||||||
|
|
Reference in a new issue