fix: harden login for MLPS requirements
This commit is contained in:
@@ -117,6 +117,7 @@ type AuthService struct {
|
||||
audits *AuditService
|
||||
issuer *TokenIssuer
|
||||
guard *sharedauth.LoginGuard
|
||||
cipher *sharedauth.PasswordCipher
|
||||
}
|
||||
|
||||
func NewAuthService(
|
||||
@@ -132,12 +133,27 @@ func NewAuthService(
|
||||
return &AuthService{accounts: accounts, audits: audits, issuer: issuer, guard: guard}
|
||||
}
|
||||
|
||||
func (s *AuthService) WithPasswordCipher(cipher *sharedauth.PasswordCipher) *AuthService {
|
||||
s.cipher = cipher
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *AuthService) PasswordPublicKey() *sharedauth.PasswordCipherPublicKey {
|
||||
if s == nil || s.cipher == nil {
|
||||
return nil
|
||||
}
|
||||
publicKey := s.cipher.PublicKey()
|
||||
return &publicKey
|
||||
}
|
||||
|
||||
type LoginInput struct {
|
||||
Username string
|
||||
Password string
|
||||
IP string
|
||||
UserAgent string
|
||||
RequestID string
|
||||
Username string
|
||||
Password string
|
||||
EncryptedPassword string
|
||||
PasswordKeyID string
|
||||
IP string
|
||||
UserAgent string
|
||||
RequestID string
|
||||
}
|
||||
|
||||
type LoginResult struct {
|
||||
@@ -176,6 +192,10 @@ func (s *AuthService) Login(ctx context.Context, in LoginInput) (*LoginResult, e
|
||||
if in.Username == "" {
|
||||
return nil, response.ErrBadRequest(40000, "invalid_payload", "username is required")
|
||||
}
|
||||
password, err := s.loginPassword(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
permit, err := s.acquireLoginPermit(ctx, in)
|
||||
if err != nil {
|
||||
@@ -183,6 +203,9 @@ func (s *AuthService) Login(ctx context.Context, in LoginInput) (*LoginResult, e
|
||||
}
|
||||
credentialsVerified := false
|
||||
defer func() {
|
||||
if permit == nil {
|
||||
return
|
||||
}
|
||||
if credentialsVerified {
|
||||
permit.RecordSuccess(ctx)
|
||||
return
|
||||
@@ -203,7 +226,7 @@ func (s *AuthService) Login(ctx context.Context, in LoginInput) (*LoginResult, e
|
||||
return nil, response.ErrForbidden(40310, "account_disabled", "账号已停用")
|
||||
}
|
||||
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(account.PasswordHash), []byte(in.Password)); err != nil {
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(account.PasswordHash), []byte(password)); err != nil {
|
||||
permit.RecordFailure(ctx)
|
||||
s.recordLoginFailure(ctx, in, "wrong_password")
|
||||
return nil, response.ErrUnauthorized(40110, "invalid_credentials", "账号或密码错误")
|
||||
@@ -237,6 +260,26 @@ func (s *AuthService) Login(ctx context.Context, in LoginInput) (*LoginResult, e
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *AuthService) loginPassword(in LoginInput) (string, error) {
|
||||
if strings.TrimSpace(in.EncryptedPassword) != "" {
|
||||
if s.cipher == nil {
|
||||
return "", response.ErrBadRequest(40002, "password_cipher_unavailable", "encrypted password is not supported by this server")
|
||||
}
|
||||
password, err := s.cipher.Decrypt(in.EncryptedPassword, in.PasswordKeyID)
|
||||
if err != nil {
|
||||
return "", response.ErrBadRequest(40003, "invalid_encrypted_password", "encrypted password is invalid")
|
||||
}
|
||||
if password == "" {
|
||||
return "", response.ErrBadRequest(40000, "invalid_payload", "password is required")
|
||||
}
|
||||
return password, nil
|
||||
}
|
||||
if in.Password == "" {
|
||||
return "", response.ErrBadRequest(40000, "invalid_payload", "password is required")
|
||||
}
|
||||
return in.Password, nil
|
||||
}
|
||||
|
||||
func (s *AuthService) acquireLoginPermit(ctx context.Context, in LoginInput) (*sharedauth.LoginPermit, error) {
|
||||
if s.guard == nil {
|
||||
return nil, nil
|
||||
|
||||
Reference in New Issue
Block a user