mirror of
https://github.com/Awuqing/BackupX.git
synced 2026-05-19 22:49:31 +08:00
feat: add complete MFA support
Add complete MFA support with TOTP, recovery codes, WebAuthn, trusted-device cookie flow, and email/SMS OTP delivery via notification channels. Security follow-up: trusted device tokens are stored in HttpOnly cookies, and SMS OTP reuses the existing Webhook notifier to avoid introducing a new dynamic URL sink.
This commit is contained in:
49
server/internal/security/recovery_code.go
Normal file
49
server/internal/security/recovery_code.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package security
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
const RecoveryCodeCount = 10
|
||||
|
||||
func GenerateRecoveryCodes(count int) ([]string, error) {
|
||||
if count <= 0 {
|
||||
count = RecoveryCodeCount
|
||||
}
|
||||
codes := make([]string, 0, count)
|
||||
for i := 0; i < count; i++ {
|
||||
raw := make([]byte, 8)
|
||||
if _, err := rand.Read(raw); err != nil {
|
||||
return nil, fmt.Errorf("generate recovery code: %w", err)
|
||||
}
|
||||
encoded := strings.ToUpper(hex.EncodeToString(raw))
|
||||
codes = append(codes, encoded[0:4]+"-"+encoded[4:8]+"-"+encoded[8:12]+"-"+encoded[12:16])
|
||||
}
|
||||
return codes, nil
|
||||
}
|
||||
|
||||
func NormalizeRecoveryCode(code string) string {
|
||||
return strings.Map(func(r rune) rune {
|
||||
if unicode.IsSpace(r) || r == '-' {
|
||||
return -1
|
||||
}
|
||||
return unicode.ToUpper(r)
|
||||
}, strings.TrimSpace(code))
|
||||
}
|
||||
|
||||
func IsRecoveryCodeCandidate(code string) bool {
|
||||
normalized := NormalizeRecoveryCode(code)
|
||||
if len(normalized) != 16 {
|
||||
return false
|
||||
}
|
||||
for _, r := range normalized {
|
||||
if !('0' <= r && r <= '9') && !('A' <= r && r <= 'F') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user