diff --git a/src/DodoSSH.Client.Shell/ViewModels/MainWindowViewModel.cs b/src/DodoSSH.Client.Shell/ViewModels/MainWindowViewModel.cs index 7fa687f..d9a5579 100644 --- a/src/DodoSSH.Client.Shell/ViewModels/MainWindowViewModel.cs +++ b/src/DodoSSH.Client.Shell/ViewModels/MainWindowViewModel.cs @@ -5,6 +5,7 @@ using System.Security.Authentication; using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; +using DodoSSH.Client.Api; using DodoSSH.Client.Auth; using DodoSSH.Client.Import; using DodoSSH.Client.ObjectStore; @@ -1012,6 +1013,12 @@ internal sealed partial class MainWindowViewModel : ObservableObject, IAsyncDisp OnPropertyChanged(nameof(IsOnline)); RaiseSyncState(); + // The browser is finished with, and what follows is a round trip to the DodoSSH server + // that can take a while or fail on its own. Saying so is the difference between a wait + // and a hang: a screen still reading "Opening your browser to sign in…" while the server + // is the thing struggling sends the user back to a browser that did nothing wrong. + StatusMessage = $"Signed in. Asking {url.Host} about your account…"; + var outcome = await Provisioner()! .RefreshAsync(ServerUrl, cancellationToken) .ConfigureAwait(true); @@ -1846,13 +1853,32 @@ internal sealed partial class MainWindowViewModel : ObservableObject, IAsyncDisp } /// - /// One case earns a translation rather than the exception's own words: pointing an HTTPS client at a - /// plaintext port reports "The SSL connection could not be established", which sends people looking - /// for a certificate problem. The scheme is the mistake, and the development stack serves HTTP, so - /// this is the first thing a new user will hit. + /// + /// Two cases earn a translation rather than the exception's own words, and both are cases where the + /// exception names a symptom belonging to somebody else's process. + /// + /// + /// Pointing an HTTPS client at a plaintext port reports "The SSL connection could not be + /// established", which sends people looking for a certificate problem. The scheme is the mistake, and + /// the development stack serves HTTP, so this is the first thing a new user will hit. + /// + /// + /// A 5xx from the DodoSSH server is the other. By the time it arrives the browser flow has already + /// succeeded — the identity provider authenticated the user and the tokens are in hand — so "The + /// server returned 500" read underneath a sign-in button is naturally taken as the sign-in having + /// failed, and the search starts in the wrong place. Naming which server, and saying that its own + /// logs hold the reason, is the whole content of the fix; the client cannot know more than that. + /// /// private static string ExplainSignInFailure(Exception exception, Uri server) { + if (exception is DodoSshApiException api && (int)api.StatusCode >= 500) + { + return $"Signing in worked. The DodoSSH server at {server.Host} then failed while answering " + + $"for your account ({(int)api.StatusCode}), which is a fault on the server rather than " + + "anything to fix here — its own logs carry the reason."; + } + var secureChannelFailed = exception is HttpRequestException && exception.GetBaseException() is AuthenticationException;