-
Notifications
You must be signed in to change notification settings - Fork 1
/
cache.go
106 lines (88 loc) · 3.19 KB
/
cache.go
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package main
import (
"fmt"
"strings"
"time"
"github.com/gobwas/glob"
"poc-jwt/cache"
)
const (
cacheAccessKeyPrefix = "auth:access"
cacheRefreshKeyPrefix = "auth:refresh"
)
type AuthenticationDB struct {
cache cache.TTLCache
refreshTokenExpiration time.Duration
accessTokenExpiration time.Duration
}
func NewAuthenticationDB(ttlCache cache.TTLCache) *AuthenticationDB {
return &AuthenticationDB{
cache: ttlCache,
refreshTokenExpiration: defaultRefreshTokenExpiration,
accessTokenExpiration: defaultAccessTokenExpiration,
}
}
func NewAuthenticationDBWithExpiration(ttlCache cache.TTLCache, refreshTokenExpiration, accessTokenExpiration time.Duration) *AuthenticationDB {
db := NewAuthenticationDB(ttlCache)
db.refreshTokenExpiration = refreshTokenExpiration
db.accessTokenExpiration = accessTokenExpiration
return db
}
func (db *AuthenticationDB) IsAccessValid(username, uuid string) bool {
val, err := db.cache.Get(db.accessKeyInCache(username, uuid))
if err != nil {
return false
}
valInt, ok := val.(int)
return ok && valInt == 1
}
func (db *AuthenticationDB) IsRefreshValid(username, uuid string) bool {
val, err := db.cache.Get(db.refreshKeyInCache(username, uuid))
if err != nil {
return false
}
valInt, ok := val.(int)
return ok && valInt == 1
}
func (db *AuthenticationDB) DeleteAllUserTokens(username string) (int, error) {
n1, err1 := db.cache.DelWithPattern(db.accessKeysOfUserPattern(username))
n2, err2 := db.cache.DelWithPattern(db.refreshKeysOfUserPattern(username))
if err1 != nil {
return n1, err1
}
return n1 + n2, err2
}
func (db *AuthenticationDB) SaveRefreshToken(username string, td TokenDetail) error {
now := time.Now()
if td.Expires == 0 || td.UUID == "" {
return fmt.Errorf("token detail requires non empty refresh expiration and uuid")
}
rt := time.Unix(td.Expires, 0)
return db.cache.SetWithTTL(db.refreshKeyInCache(username, td.UUID), 1, rt.Sub(now))
}
func (db *AuthenticationDB) SaveAccessToken(username string, td TokenDetail) error {
now := time.Now()
if td.Expires == 0 || td.UUID == "" {
return fmt.Errorf("token detail requires non empty access expiration and uuid")
}
rt := time.Unix(td.Expires, 0)
return db.cache.SetWithTTL(db.accessKeyInCache(username, td.UUID), 1, rt.Sub(now))
}
func (db *AuthenticationDB) DeleteRefreshToken(username string, uuid string) (bool, error) {
return db.cache.Del(db.refreshKeyInCache(username, uuid))
}
func (db *AuthenticationDB) DeleteAccessToken(username string, uuid string) (bool, error) {
return db.cache.Del(db.accessKeyInCache(username, uuid))
}
func (db *AuthenticationDB) accessKeyInCache(username string, uuid string) string {
return strings.Join([]string{cacheAccessKeyPrefix, username, uuid}, ":")
}
func (db *AuthenticationDB) refreshKeyInCache(username string, uuid string) string {
return strings.Join([]string{cacheRefreshKeyPrefix, username, uuid}, ":")
}
func (db *AuthenticationDB) accessKeysOfUserPattern(username string) glob.Glob {
return glob.MustCompile(cacheAccessKeyPrefix + ":" + username + ":*")
}
func (db *AuthenticationDB) refreshKeysOfUserPattern(username string) glob.Glob {
return glob.MustCompile(cacheRefreshKeyPrefix + ":" + username + ":*")
}