refactor auth interface to return error when verify failure (#22119)

This PR changed the Auth interface signature from 
`Verify(http *http.Request, w http.ResponseWriter, store DataStore, sess
SessionStore) *user_model.User`
to 
`Verify(http *http.Request, w http.ResponseWriter, store DataStore, sess
SessionStore) (*user_model.User, error)`.

There is a new return argument `error` which means the verification
condition matched but verify process failed, we should stop the auth
process.

Before this PR, when return a `nil` user, we don't know the reason why
it returned `nil`. If the match condition is not satisfied or it
verified failure? For these two different results, we should have
different handler. If the match condition is not satisfied, we should
try next auth method and if there is no more auth method, it's an
anonymous user. If the condition matched but verify failed, the auth
process should be stop and return immediately.

This will fix #20563

Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
Co-authored-by: Jason Song <i@wolfogre.com>
This commit is contained in:
Lunny Xiao 2022-12-28 13:53:28 +08:00 committed by GitHub
parent 7cc7db73b9
commit ca67c5a8a7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 111 additions and 79 deletions

View file

@ -77,15 +77,15 @@ func (s *SSPI) Free() error {
// If authentication is successful, returns the corresponding user object.
// If negotiation should continue or authentication fails, immediately returns a 401 HTTP
// response code, as required by the SPNEGO protocol.
func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *user_model.User {
func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) {
if !s.shouldAuthenticate(req) {
return nil
return nil, nil
}
cfg, err := s.getConfig()
if err != nil {
log.Error("could not get SSPI config: %v", err)
return nil
return nil, err
}
log.Trace("SSPI Authorization: Attempting to authenticate")
@ -108,7 +108,7 @@ func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore,
log.Error("%v", err)
}
return nil
return nil, err
}
if outToken != "" {
sspiAuth.AppendAuthenticateHeader(w, outToken)
@ -116,7 +116,7 @@ func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore,
username := sanitizeUsername(userInfo.Username, cfg)
if len(username) == 0 {
return nil
return nil, nil
}
log.Info("Authenticated as %s\n", username)
@ -124,16 +124,16 @@ func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore,
if err != nil {
if !user_model.IsErrUserNotExist(err) {
log.Error("GetUserByName: %v", err)
return nil
return nil, err
}
if !cfg.AutoCreateUsers {
log.Error("User '%s' not found", username)
return nil
return nil, nil
}
user, err = s.newUser(username, cfg)
if err != nil {
log.Error("CreateUser: %v", err)
return nil
return nil, err
}
}
@ -143,7 +143,7 @@ func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore,
}
log.Trace("SSPI Authorization: Logged in user %-v", user)
return user
return user, nil
}
// getConfig retrieves the SSPI configuration from login sources