Authenticate a user from a password
(ctx context.Context, tx *storage.Connection, password string, decryptionKeys map[string]string, encrypt bool, encryptionKeyID string)
| 385 | |
| 386 | // Authenticate a user from a password |
| 387 | func (u *User) Authenticate(ctx context.Context, tx *storage.Connection, password string, decryptionKeys map[string]string, encrypt bool, encryptionKeyID string) (bool, bool, error) { |
| 388 | if u.EncryptedPassword == nil { |
| 389 | return false, false, nil |
| 390 | } |
| 391 | |
| 392 | hash := *u.EncryptedPassword |
| 393 | |
| 394 | if hash == "" { |
| 395 | return false, false, nil |
| 396 | } |
| 397 | |
| 398 | es := crypto.ParseEncryptedString(hash) |
| 399 | if es != nil { |
| 400 | h, err := es.Decrypt(u.ID.String(), decryptionKeys) |
| 401 | if err != nil { |
| 402 | return false, false, err |
| 403 | } |
| 404 | |
| 405 | hash = string(h) |
| 406 | } |
| 407 | |
| 408 | compareErr := crypto.CompareHashAndPassword(ctx, hash, password) |
| 409 | |
| 410 | if !strings.HasPrefix(hash, crypto.Argon2Prefix) && !strings.HasPrefix(hash, crypto.FirebaseScryptPrefix) { |
| 411 | // check if cost exceeds default cost or is too low |
| 412 | cost, err := bcrypt.Cost([]byte(hash)) |
| 413 | if err != nil { |
| 414 | return compareErr == nil, false, err |
| 415 | } |
| 416 | |
| 417 | if cost > bcrypt.DefaultCost || cost == bcrypt.MinCost { |
| 418 | // don't bother with encrypting the password in Authenticate |
| 419 | // since it's handled separately |
| 420 | if err := u.SetPassword(ctx, password, false, "", ""); err != nil { |
| 421 | return compareErr == nil, false, err |
| 422 | } |
| 423 | } |
| 424 | } |
| 425 | |
| 426 | return compareErr == nil, encrypt && (es == nil || es.ShouldReEncrypt(encryptionKeyID)), nil |
| 427 | } |
| 428 | |
| 429 | // ConfirmReauthentication resets the reauthentication token |
| 430 | func (u *User) ConfirmReauthentication(tx *storage.Connection) error { |