An atproto PDS written in Go

fix listing of active oauth sessions

Changed files
+48 -12
oauth
server
+32
oauth/helpers.go
··· 4 "errors" 5 "fmt" 6 "net/url" 7 8 "github.com/haileyok/cocoon/internal/helpers" 9 "github.com/haileyok/cocoon/oauth/constants" 10 ) 11 12 func GenerateCode() string { ··· 46 47 return reqId, nil 48 }
··· 4 "errors" 5 "fmt" 6 "net/url" 7 + "time" 8 9 "github.com/haileyok/cocoon/internal/helpers" 10 "github.com/haileyok/cocoon/oauth/constants" 11 + "github.com/haileyok/cocoon/oauth/provider" 12 ) 13 14 func GenerateCode() string { ··· 48 49 return reqId, nil 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
··· 3 import ( 4 "time" 5 6 "github.com/haileyok/cocoon/oauth/provider" 7 "github.com/labstack/echo/v4" 8 ) ··· 13 return e.Redirect(303, "/account/signin") 14 } 15 16 - now := time.Now() 17 18 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 { 20 s.logger.Error("couldnt fetch oauth sessions for account", "did", repo.Repo.Did, "error", err) 21 sess.AddFlash("Unable to fetch sessions. See server logs for more details.", "error") 22 sess.Save(e.Request(), e.Response()) 23 return e.Render(200, "account.html", map[string]any{ 24 "flashes": getFlashesFromSession(e, sess), 25 }) 26 } 27 28 tokenInfo := []map[string]string{}
··· 3 import ( 4 "time" 5 6 + "github.com/haileyok/cocoon/oauth" 7 + "github.com/haileyok/cocoon/oauth/constants" 8 "github.com/haileyok/cocoon/oauth/provider" 9 "github.com/labstack/echo/v4" 10 ) ··· 15 return e.Redirect(303, "/account/signin") 16 } 17 18 + oldestPossibleSession := time.Now().Add(constants.ConfidentialClientSessionLifetime) 19 20 var tokens []provider.OauthToken 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 { 22 s.logger.Error("couldnt fetch oauth sessions for account", "did", repo.Repo.Did, "error", err) 23 sess.AddFlash("Unable to fetch sessions. See server logs for more details.", "error") 24 sess.Save(e.Request(), e.Response()) 25 return e.Render(200, "account.html", map[string]any{ 26 "flashes": getFlashesFromSession(e, sess), 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) 37 } 38 39 tokenInfo := []map[string]string{}
+3 -10
server/handle_oauth_token.go
··· 203 return helpers.InputError(e, to.StringPtr("dpop proof does not match expected jkt")) 204 } 205 206 - sessionLifetime := constants.PublicClientSessionLifetime 207 - refreshLifetime := constants.PublicClientRefreshLifetime 208 - if clientAuth.Method != "none" { 209 - sessionLifetime = constants.ConfidentialClientSessionLifetime 210 - refreshLifetime = constants.ConfidentialClientRefreshLifetime 211 - } 212 213 - sessionAge := time.Since(oauthToken.CreatedAt) 214 - if sessionAge > sessionLifetime { 215 return helpers.InputError(e, to.StringPtr("Session expired")) 216 } 217 218 - refreshAge := time.Since(oauthToken.UpdatedAt) 219 - if refreshAge > refreshLifetime { 220 return helpers.InputError(e, to.StringPtr("Refresh token expired")) 221 } 222
··· 203 return helpers.InputError(e, to.StringPtr("dpop proof does not match expected jkt")) 204 } 205 206 + ageRes := oauth.GetSessionAgeFromToken(oauthToken) 207 208 + if ageRes.SessionExpired { 209 return helpers.InputError(e, to.StringPtr("Session expired")) 210 } 211 212 + if ageRes.RefreshExpired { 213 return helpers.InputError(e, to.StringPtr("Refresh token expired")) 214 } 215