Public Access
Spelunk sign-in: end it with a refused DodoSSH resume, keep the token the check rotated, and send the token by the sign-in's own address
A DodoSSH resume the provider refuses now signs the device out of every Spelunk as well, as the check before a Spelunk connection already did, so the README's "an account the provider no longer signs in is signed out of DodoSSH and of every Spelunk" holds whichever finds it first. The forced refresh that check makes is written down at once rather than at the next sync pass, so a crash in between cannot cost a browser sign-in on the next launch. The tunnel is opened at the sign-in's own address rather than the route's: the same string, but the token going where it came from is now said where it is sent. Relaunches in the shell tests use the scripted Spelunk sign-in too, so none can open a browser or send a sign-out anywhere real. Fixes a doc comment the account-refused handler had split, a README line still pointing at the key picker, and the Android composition's comment on which redirect Spelunk allows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
57d3d3c801
commit
abd7e56bb5
7 files changed
+84
-15
No files matched your search
@@ -680,6 +680,33 @@ public sealed partial class ShellFlowTests
|
||||
shell.IsOnline.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ADodoSshSignInRefusedOnResume_SignsThisDeviceOutOfEverySpelunkToo()
|
||||
{
|
||||
await ReadyToConnectThroughSpelunkAsync();
|
||||
await shell.Vault!.SyncOnOpenAsync(Token);
|
||||
await shell.LockCommand.ExecuteAsync(null);
|
||||
spelunkAccounts.SignedOut.ShouldBeEmpty();
|
||||
|
||||
resumeFailure = new OidcException("The token endpoint returned 400: Account disabled.", "invalid_grant");
|
||||
|
||||
var relaunch = Relaunch(resume: ResumeAsync);
|
||||
await using var _ = relaunch.ConfigureAwait(false);
|
||||
|
||||
await relaunch.StartAsync(Token);
|
||||
relaunch.Passphrase = Passphrase;
|
||||
await relaunch.UnlockCommand.ExecuteAsync(null);
|
||||
await relaunch.Vault.ShouldNotBeNull().SyncOnOpenAsync(Token);
|
||||
|
||||
// The token Spelunk is told to end is the one the first launch kept: the sign-in outlived the lock and
|
||||
// the relaunch, and went only when DodoSSH's own did.
|
||||
relaunch.IsOnline.ShouldBeFalse();
|
||||
spelunkAccounts.SignedOut.ShouldBe([SpelunkToken]);
|
||||
relaunch.Vault.SpelunkSignIns.ShouldBeEmpty();
|
||||
(await relaunch.Vault.Session.SpelunkSignIns.ListAsync(Token)).ShouldBeEmpty();
|
||||
relaunch.Vault.Status.ShouldNotBeNull().ShouldContain("signed out of Spelunk");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SigningOutOfSpelunk_OnTheSecurityPage_EndsItThereAndHere()
|
||||
{
|
||||
|
||||
@@ -9666,7 +9666,11 @@ public sealed partial class ShellFlowTests : IAsyncLifetime
|
||||
TimeProvider.System,
|
||||
ssh,
|
||||
CheapProfile,
|
||||
resume);
|
||||
resume,
|
||||
|
||||
// The same stand-in as the first launch's, so a relaunch neither opens a browser at Spelunk nor
|
||||
// sends a sign-out anywhere real.
|
||||
spelunkAccounts: spelunkAccounts);
|
||||
|
||||
private async Task SignedInAsync()
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user