diff --git a/client/web/web.go b/client/web/web.go index 0cf4acfc9..7cbd413f0 100644 --- a/client/web/web.go +++ b/client/web/web.go @@ -292,7 +292,6 @@ var ( errNotUsingTailscale = errors.New("not-using-tailscale") errTaggedSource = errors.New("tagged-source") errNotOwner = errors.New("not-owner") - errFailedAuth = errors.New("failed-auth") ) // getTailscaleBrowserSession retrieves the browser session associated with @@ -413,12 +412,12 @@ func (s *Server) serveTailscaleAuth(w http.ResponseWriter, r *http.Request) { if r.URL.Query().Get("wait") == "true" { // Client requested we block until user completes auth. d, err := s.getOrAwaitAuth(r.Context(), session.AuthID, whois.Node.ID) - if errors.Is(err, errFailedAuth) { - http.Error(w, "user is unauthorized", http.StatusUnauthorized) - s.browserSessions.Delete(session.ID) // clean up the failed session - return - } else if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + if err != nil { + http.Error(w, err.Error(), http.StatusUnauthorized) + // Clean up the session. Doing this on any error from control + // server to avoid the user getting stuck with a bad session + // cookie. + s.browserSessions.Delete(session.ID) return } if d.Complete { @@ -485,11 +484,7 @@ func (s *Server) getOrAwaitAuth(ctx context.Context, authID string, src tailcfg. } body, _ := io.ReadAll(resp.Body) resp.Body.Close() - if resp.StatusCode == http.StatusUnauthorized { - // User completed auth, but control server reported - // them unauthorized to manage this node. - return nil, errFailedAuth - } else if resp.StatusCode != http.StatusOK { + if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("failed request: %s", body) } var authResp *tailcfg.WebClientAuthResponse diff --git a/ipn/localapi/localapi.go b/ipn/localapi/localapi.go index 4151d94e7..ef820537f 100644 --- a/ipn/localapi/localapi.go +++ b/ipn/localapi/localapi.go @@ -2172,12 +2172,13 @@ func (h *Handler) serveDebugWebClient(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) return } - defer resp.Body.Close() - - if _, err := io.Copy(w, resp.Body); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + body, _ := io.ReadAll(resp.Body) + resp.Body.Close() + if resp.StatusCode != http.StatusOK { + http.Error(w, string(body), resp.StatusCode) return } + w.Write(body) w.Header().Set("Content-Type", "application/json") }