+32
oauth/helpers.go
+32
oauth/helpers.go
···
4
4
"errors"
5
5
"fmt"
6
6
"net/url"
7
+
"time"
7
8
8
9
"github.com/haileyok/cocoon/internal/helpers"
9
10
"github.com/haileyok/cocoon/oauth/constants"
11
+
"github.com/haileyok/cocoon/oauth/provider"
10
12
)
11
13
12
14
func GenerateCode() string {
···
46
48
47
49
return reqId, nil
48
50
}
51
+
52
+
type SessionAgeResult struct {
53
+
SessionAge time.Duration
54
+
RefreshAge time.Duration
55
+
SessionExpired bool
56
+
RefreshExpired bool
57
+
}
58
+
59
+
func GetSessionAgeFromToken(t provider.OauthToken) SessionAgeResult {
60
+
sessionLifetime := constants.PublicClientSessionLifetime
61
+
refreshLifetime := constants.PublicClientRefreshLifetime
62
+
if t.ClientAuth.Method != "none" {
63
+
sessionLifetime = constants.ConfidentialClientSessionLifetime
64
+
refreshLifetime = constants.ConfidentialClientRefreshLifetime
65
+
}
66
+
67
+
res := SessionAgeResult{}
68
+
69
+
res.SessionAge = time.Since(t.CreatedAt)
70
+
if res.SessionAge > sessionLifetime {
71
+
res.SessionExpired = true
72
+
}
73
+
74
+
refreshAge := time.Since(t.UpdatedAt)
75
+
if refreshAge > refreshLifetime {
76
+
res.RefreshExpired = true
77
+
}
78
+
79
+
return res
80
+
}
+13
-2
server/handle_account.go
+13
-2
server/handle_account.go
···
3
3
import (
4
4
"time"
5
5
6
+
"github.com/haileyok/cocoon/oauth"
7
+
"github.com/haileyok/cocoon/oauth/constants"
6
8
"github.com/haileyok/cocoon/oauth/provider"
7
9
"github.com/labstack/echo/v4"
8
10
)
···
13
15
return e.Redirect(303, "/account/signin")
14
16
}
15
17
16
-
now := time.Now()
18
+
oldestPossibleSession := time.Now().Add(constants.ConfidentialClientSessionLifetime)
17
19
18
20
var tokens []provider.OauthToken
19
-
if err := s.db.Raw("SELECT * FROM oauth_tokens WHERE sub = ? AND expires_at >= ? ORDER BY created_at ASC", nil, repo.Repo.Did, now).Scan(&tokens).Error; err != nil {
21
+
if err := s.db.Raw("SELECT * FROM oauth_tokens WHERE sub = ? AND created_at < ? ORDER BY created_at ASC", nil, repo.Repo.Did, oldestPossibleSession).Scan(&tokens).Error; err != nil {
20
22
s.logger.Error("couldnt fetch oauth sessions for account", "did", repo.Repo.Did, "error", err)
21
23
sess.AddFlash("Unable to fetch sessions. See server logs for more details.", "error")
22
24
sess.Save(e.Request(), e.Response())
23
25
return e.Render(200, "account.html", map[string]any{
24
26
"flashes": getFlashesFromSession(e, sess),
25
27
})
28
+
}
29
+
30
+
var filtered []provider.OauthToken
31
+
for _, t := range tokens {
32
+
ageRes := oauth.GetSessionAgeFromToken(t)
33
+
if ageRes.SessionExpired {
34
+
continue
35
+
}
36
+
filtered = append(filtered, t)
26
37
}
27
38
28
39
tokenInfo := []map[string]string{}
+3
-10
server/handle_oauth_token.go
+3
-10
server/handle_oauth_token.go
···
203
203
return helpers.InputError(e, to.StringPtr("dpop proof does not match expected jkt"))
204
204
}
205
205
206
-
sessionLifetime := constants.PublicClientSessionLifetime
207
-
refreshLifetime := constants.PublicClientRefreshLifetime
208
-
if clientAuth.Method != "none" {
209
-
sessionLifetime = constants.ConfidentialClientSessionLifetime
210
-
refreshLifetime = constants.ConfidentialClientRefreshLifetime
211
-
}
206
+
ageRes := oauth.GetSessionAgeFromToken(oauthToken)
212
207
213
-
sessionAge := time.Since(oauthToken.CreatedAt)
214
-
if sessionAge > sessionLifetime {
208
+
if ageRes.SessionExpired {
215
209
return helpers.InputError(e, to.StringPtr("Session expired"))
216
210
}
217
211
218
-
refreshAge := time.Since(oauthToken.UpdatedAt)
219
-
if refreshAge > refreshLifetime {
212
+
if ageRes.RefreshExpired {
220
213
return helpers.InputError(e, to.StringPtr("Refresh token expired"))
221
214
}
222
215