package public import ( "encoding/json" "errors" "net/http" "time" "git.sendico.io/tech/sxchnge/product/auth/http/v1/request" "git.sendico.io/tech/sxchnge/product/auth/http/v1/response" "git.sendico.io/tech/sxchnge/product/sessions/browser" "git.sendico.io/tech/sxchnge/shared/http/response" "git.sendico.io/tech/sxchnge/shared/service" "go.uber.org/zap" ) func (pr *PublicRouter) refreshAccessToken(r *http.Request) http.HandlerFunc { pr.logger.Debug("Processing access token refresh request") var req srequest.AccessTokenRefresh if err := json.NewDecoder(r.Body).Decode(&req); err != nil { pr.logger.Info("Failed to decode token rotation request", zap.Error(err)) return response.BadPayload(pr.logger, mservice.RefreshTokens, err) } account, token, refreshToken, err := pr.validateRefreshToken(r.Context(), r, &req) if err != nil { if errors.Is(err, errClientIPNotAllowed) { return response.Forbidden(pr.logger, pr.service, "ip_not_allowed", "request ip is not allowed for this client") } if isExpectedRefreshValidationError(err) { pr.logger.Debug("Access token refresh rejected", zap.Error(err)) return pr.rejectRefresh(r, err) } pr.logger.Warn("Failed to process access token refreshment request", zap.Error(err)) return response.Auto(pr.logger, pr.service, err) } if browser.UsesCookie(r) && refreshToken.ExpiresAt.Before(time.Now().Add(7*24*time.Hour)) { return pr.refreshAndRespondLogin(r.Context(), r, &refreshToken.SessionIdentifier, account) } return sresponse.Account(pr.logger, account, token) } func (pr *PublicRouter) rejectRefresh(r *http.Request, err error) http.HandlerFunc { handler := response.Auto(pr.logger, pr.service, err) if !browser.UsesCookie(r) { return handler } return func(w http.ResponseWriter, request *http.Request) { browser.ClearRefreshCookie(w, request) handler.ServeHTTP(w, request) } }