-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauth.go
More file actions
76 lines (65 loc) · 2.08 KB
/
auth.go
File metadata and controls
76 lines (65 loc) · 2.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//go:build !wasm
package user
import (
"github.com/tinywasm/orm"
"golang.org/x/crypto/bcrypt"
)
var PasswordHashCost = bcrypt.DefaultCost
var dummyHashOnce []byte
func getDummyHash() []byte {
if len(dummyHashOnce) == 0 {
dummyHashOnce, _ = bcrypt.GenerateFromPassword([]byte("dummy"), PasswordHashCost)
}
return dummyHashOnce
}
func (m *Module) Login(email, password string) (User, error) {
u, err := getUserByEmail(m.db, m.ucache, email)
if err != nil {
// Dummy bcrypt: constant-time regardless of user existence.
// Dynamically generate a valid dummy hash for the configured cost to match timing exactly.
bcrypt.CompareHashAndPassword(getDummyHash(), []byte(password))
return User{}, ErrInvalidCredentials
}
if u.Status != "active" {
m.notify(SecurityEvent{Type: EventNonActiveAccess, UserID: u.ID})
bcrypt.CompareHashAndPassword(getDummyHash(), []byte(password))
return User{}, ErrSuspended
}
identity, err := getLocalIdentity(m.db, u.ID)
if err != nil {
bcrypt.CompareHashAndPassword(getDummyHash(), []byte(password))
return User{}, ErrInvalidCredentials
}
if err := bcrypt.CompareHashAndPassword([]byte(identity.ProviderID), []byte(password)); err != nil {
return User{}, ErrInvalidCredentials
}
return u, nil
}
func getLocalIdentity(db *orm.DB, userID string) (Identity, error) {
return getIdentityByUserAndProvider(db, userID, "local")
}
func (m *Module) SetPassword(userID, password string) error {
if len(password) < 8 {
return ErrWeakPassword
}
if m.config.OnPasswordValidate != nil {
if err := m.config.OnPasswordValidate(password); err != nil {
return err
}
}
hash, err := bcrypt.GenerateFromPassword([]byte(password), PasswordHashCost)
if err != nil {
return err
}
return upsertIdentity(m.db, userID, "local", string(hash), "")
}
func (m *Module) VerifyPassword(userID, password string) error {
identity, err := getLocalIdentity(m.db, userID)
if err != nil {
return ErrInvalidCredentials
}
if err := bcrypt.CompareHashAndPassword([]byte(identity.ProviderID), []byte(password)); err != nil {
return ErrInvalidCredentials
}
return nil
}