Explorar el Código

ipn/localapi,client/web: clean up auth error handling

This commit makes two changes to the web client auth flow error
handling:

1. Properly passes back the error code from the noise request from
   the localapi. Previously we were using io.Copy, which was always
   setting a 200 response status code.
2. Clean up web client browser sessions on any /wait endpoint error.
   This avoids the user getting in a stuck state if something goes
   wrong with their auth path.

Updates tailscale/corp#14335

Signed-off-by: Sonia Appasamy <[email protected]>
Sonia Appasamy hace 2 años
padre
commit
68da15516f
Se han modificado 2 ficheros con 12 adiciones y 16 borrados
  1. 7 12
      client/web/web.go
  2. 5 4
      ipn/localapi/localapi.go

+ 7 - 12
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

+ 5 - 4
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")
 }