Files

65 lines
2.2 KiB
Go

package handlers
import (
"log/slog"
"net/http"
"atcr.io/pkg/appview/db"
"atcr.io/pkg/auth/oauth"
indigooauth "github.com/bluesky-social/indigo/atproto/auth/oauth"
"github.com/bluesky-social/indigo/atproto/syntax"
)
// LogoutHandler handles user logout with proper OAuth token revocation
type LogoutHandler struct {
OAuthClientApp *indigooauth.ClientApp
Refresher *oauth.Refresher
SessionStore *db.SessionStore
OAuthStore *db.OAuthStore
}
func (h *LogoutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Get UI session ID from cookie
uiSessionID, hasSession := db.GetSessionID(r)
if !hasSession {
// No session to logout from, just redirect
http.Redirect(w, r, "/", http.StatusFound)
return
}
// Get UI session to extract OAuth session ID and user info
uiSession, ok := h.SessionStore.Get(uiSessionID)
if ok && uiSession != nil && uiSession.DID != "" {
// Parse DID for OAuth logout
did, err := syntax.ParseDID(uiSession.DID)
if err != nil {
slog.Warn("Failed to parse DID for logout", "component", "logout", "did", uiSession.DID, "error", err)
} else {
// Attempt to revoke OAuth tokens on PDS side
if uiSession.OAuthSessionID != "" {
// Call indigo's Logout to revoke tokens on PDS
if err := h.OAuthClientApp.Logout(r.Context(), did, uiSession.OAuthSessionID); err != nil {
// Log error but don't block logout - best effort revocation
slog.Warn("Failed to revoke OAuth tokens on PDS", "component", "logout", "did", uiSession.DID, "error", err)
} else {
slog.Info("Successfully revoked OAuth tokens on PDS", "component", "logout", "did", uiSession.DID)
}
// Delete OAuth session from database (cleanup, might already be done by Logout)
if err := h.OAuthStore.DeleteSession(r.Context(), did, uiSession.OAuthSessionID); err != nil {
slog.Warn("Failed to delete OAuth session from database", "component", "logout", "error", err)
}
} else {
slog.Warn("No OAuth session ID found for user", "component", "logout", "did", uiSession.DID)
}
}
}
// Always delete UI session and clear cookie, even if OAuth revocation failed
h.SessionStore.Delete(uiSessionID)
db.ClearCookie(w)
// Redirect to home page
http.Redirect(w, r, "/", http.StatusFound)
}