package public import ( "encoding/json" "net/http" "git.sendico.io/tech/sxchnge/product/auth/request" "git.sendico.io/tech/sxchnge/product/sessions/browser" "git.sendico.io/tech/sxchnge/product/sessions/metrics" "git.sendico.io/tech/sxchnge/shared/http/response" "git.sendico.io/tech/sxchnge/shared/service" "go.uber.org/zap" ) func (pr *PublicRouter) logout(r *http.Request) http.HandlerFunc { respond := func(handler http.HandlerFunc, clearCookie bool) http.HandlerFunc { if !clearCookie || !browser.UsesCookie(r) { return handler } return func(w http.ResponseWriter, request *http.Request) { browser.ClearRefreshCookie(w, request) handler.ServeHTTP(w, request) } } var req srequest.AccessTokenRefresh if err := json.NewDecoder(r.Body).Decode(&req); err != nil { pr.logger.Info("Rejected malformed logout request", zap.Error(err)) return respond(response.BadPayload(pr.logger, mservice.RefreshTokens, err), false) } credential, err := browser.RefreshCredential(r, req.RefreshToken) if err != nil { sessionmetrics.Observe(sessionmetrics.CurrentLogout, sessionmetrics.AlreadyInactive) return respond(response.Success(pr.logger), true) } req.RefreshToken = credential if req.ClientID == "" || req.DeviceID == "" || req.RefreshToken == "" { sessionmetrics.Observe(sessionmetrics.CurrentLogout, sessionmetrics.MissingIdentity) return respond(response.BadRequest(pr.logger, pr.service, "missing_session", "refresh token and session identifier are required"), false) } revoked, err := pr.rtdb.RevokeToken(r.Context(), &req) if err != nil { sessionmetrics.Observe(sessionmetrics.CurrentLogout, sessionmetrics.StorageError) pr.logger.Warn("Failed to revoke current session", zap.Error(err), zap.String("client_id", req.ClientID), zap.String("device_id", req.DeviceID)) return respond(response.Internal(pr.logger, pr.service, err), false) } if !revoked { sessionmetrics.Observe(sessionmetrics.CurrentLogout, sessionmetrics.AlreadyInactive) return respond(response.Success(pr.logger), true) } sessionmetrics.Observe(sessionmetrics.CurrentLogout, sessionmetrics.Succeeded) pr.logger.Info("Current session revoked", zap.String("client_id", req.ClientID), zap.String("device_id", req.DeviceID)) return respond(response.Success(pr.logger), true) }