forked from pydio/cells
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dex-sql.go
141 lines (119 loc) · 3.31 KB
/
dex-sql.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package auth
import (
"context"
"encoding/json"
"time"
"github.com/coreos/dex/storage"
"github.com/pydio/cells/common"
"github.com/pydio/cells/common/log"
"github.com/pydio/cells/common/sql"
)
type dexSql struct {
sql.DAO
}
// Init handler for the SQL DAO
func (s *dexSql) Init(options common.ConfigValues) error {
// super
s.DAO.Init(options)
// Do NOT prepare the stmts now
return nil
}
// DexPruneOfflineSessions browses existing sessions looking of refresh tokens totally expired
func (s *dexSql) DexPruneOfflineSessions(c Config) (pruned int64, e error) {
stmt, e := s.DB().Prepare("SELECT * FROM dex_offline_session")
if e != nil {
return 0, e
}
defer stmt.Close()
rows, e := stmt.Query()
if e != nil {
return 0, e
}
defer rows.Close()
for rows.Next() {
var uId, connId string
var jsonData []byte
if err := rows.Scan(&uId, &connId, &jsonData); err != nil {
log.Logger(context.Background()).Error("Cannot scan row for offline session")
continue
}
var tokens map[string]*storage.RefreshTokenRef
if e := json.Unmarshal(jsonData, &tokens); e != nil {
log.Logger(context.Background()).Error("Cannot scan unmarshall data for offline session")
continue
}
session := &storage.OfflineSessions{
UserID: uId,
ConnID: connId,
Refresh: tokens,
}
needsDeletion := false
for _, token := range session.Refresh {
if s.needsDeletion(token, c) {
needsDeletion = true
break
}
}
if !needsDeletion {
continue
}
// This session needs deletion. Delete offline session and refresh_token
if e = s.DexDeleteOfflineSessions(c, session.UserID, session.ConnID); e == nil {
pruned++
log.Logger(context.Background()).Debug("Successfully deleted offline session and refresh token")
} else {
log.Logger(context.Background()).Error("Could not delete offline session")
}
}
return
}
// DexDeleteOfflineSessions Delete offline session and refresh token based on uuid / session uuid (nonce)
func (s *dexSql) DexDeleteOfflineSessions(c Config, userUuid string, sessionUuid string) error {
offline, e := s.DB().Prepare(`DELETE FROM dex_offline_session WHERE user_id=? AND conn_id=?`)
if e != nil {
return e
}
defer offline.Close()
refresh, e := s.DB().Prepare(`DELETE FROM dex_refresh_token WHERE claims_user_id=? AND nonce=?`)
if e != nil {
return e
}
defer refresh.Close()
// This session needs deletion. Delete offline session and refresh_token
if _, e1 := offline.Exec(userUuid, sessionUuid); e1 == nil {
if _, e2 := refresh.Exec(userUuid, sessionUuid); e2 == nil {
log.Logger(context.Background()).Debug("Deleted offline session and refresh token")
} else {
return e2
}
} else {
return e1
}
return nil
}
func (s *dexSql) needsDeletion(refreshToken *storage.RefreshTokenRef, c Config) bool {
var client storage.Client
found := false
for _, staticClient := range c.StaticClients {
if staticClient.ID == refreshToken.ClientID {
client = staticClient
found = true
}
}
if !found || client.RefreshTokensExpiry == "" {
return false
}
var ref time.Time
if client.OfflineSessionsSliding {
ref = refreshToken.LastUsed
} else {
ref = refreshToken.CreatedAt
}
if expiry, e := time.ParseDuration(client.RefreshTokensExpiry); e != nil {
return false
} else if time.Now().After(ref.Add(expiry)) {
return true
} else {
return false
}
}