factor out kjol auth
This commit is contained in:
67
go/auth/password.go
Normal file
67
go/auth/password.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// CheckPassword reports whether a password satisfies the configured policy,
|
||||
// returning an error phrased for the end user (the caller can surface it
|
||||
// verbatim on a signup or change-password form).
|
||||
func (a *Authenticator) CheckPassword(password string) error {
|
||||
return CheckPasswordPolicy(a.cfg.Password, password)
|
||||
}
|
||||
|
||||
// CheckPasswordPolicy is CheckPassword against an explicit policy, for callers
|
||||
// that validate a password without an Authenticator in hand.
|
||||
func CheckPasswordPolicy(policy PasswordPolicy, password string) error {
|
||||
if strings.TrimSpace(password) == "" {
|
||||
return errors.New("Password cannot be blank.")
|
||||
}
|
||||
|
||||
if len(password) < policy.MinLength {
|
||||
return errors.New("Password must be at least " + strconv.Itoa(policy.MinLength) + " characters long.")
|
||||
}
|
||||
|
||||
var uppercase, lowercase, numbers, symbols int
|
||||
for _, r := range password {
|
||||
switch {
|
||||
case unicode.IsUpper(r):
|
||||
uppercase++
|
||||
case unicode.IsLower(r):
|
||||
lowercase++
|
||||
case unicode.IsNumber(r):
|
||||
numbers++
|
||||
default:
|
||||
symbols++
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case uppercase < policy.RequiredUppercase:
|
||||
return errors.New("Password must contain at least " + strconv.Itoa(policy.RequiredUppercase) + " uppercase character(s).")
|
||||
case lowercase < policy.RequiredLowercase:
|
||||
return errors.New("Password must contain at least " + strconv.Itoa(policy.RequiredLowercase) + " lowercase character(s).")
|
||||
case numbers < policy.RequiredNumbers:
|
||||
return errors.New("Password must contain at least " + strconv.Itoa(policy.RequiredNumbers) + " number(s).")
|
||||
case symbols < policy.RequiredSymbols:
|
||||
return errors.New("Password must contain at least " + strconv.Itoa(policy.RequiredSymbols) + " symbol(s).")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GeneratePasswordResetToken returns a 32-byte crypto-random token, hex-encoded
|
||||
// (64 characters). The app stores it against the user with an expiry and mails
|
||||
// the same string out.
|
||||
func GeneratePasswordResetToken() (string, error) {
|
||||
b := make([]byte, 32)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return hex.EncodeToString(b), nil
|
||||
}
|
||||
Reference in New Issue
Block a user