Use window.nostr (NIP-46/Amber bunker) on the mobile login page

Replaces the fragile NIP-55 intent/callback round-trip with the same
mechanism the desktop login uses: openNostrLogin signs the session
challenge via window.nostr — provided by an extension or by
window.nostr.js over a persistent NIP-46 connection (Amber pairing with
permissions). The listener stores a LoginKey for the page's k1 and
navigates to the completion route, which issues the token and redirects
into the app via the verified App Link handoff.
This commit is contained in:
HolgerHatGarKeineNode
2026-06-11 20:47:02 +02:00
parent 7531f28f22
commit c30f1932e4
2 changed files with 118 additions and 41 deletions
+21
View File
@@ -201,6 +201,27 @@ it('lets an already authenticated user connect the app and replaces tokens of th
expect($user->tokens()->where('name', 'Pixel 10')->count())->toBe(1);
});
it('completes a window.nostr login on the mobile page via LoginKey and the completion route', function () {
Queue::fake();
$component = Livewire\Livewire::withQueryParams(['redirect_uri' => 'einundzwanzig://auth', 'device_name' => 'Pixel 10'])
->test('auth.mobile-login');
// Helper from NostrLoginTest: signs the challenge stored in the session.
[$signedEvent, $npub] = makeSignedNostrLoginEvent();
$k1 = $component->get('k1');
$component
->dispatch('nostrLoggedIn', signedEvent: $signedEvent)
->assertRedirect(route('auth.mobile.complete', ['k1' => $k1]));
$user = User::query()->where('nostr', $npub)->first();
expect($user)->not->toBeNull();
expect(LoginKey::query()->where('k1', $k1)->value('user_id'))->toBe($user->id);
Queue::assertPushed(FetchNostrProfileJob::class);
});
it('shows the confirmation screen instead of the login methods for authenticated users', function () {
$user = User::factory()->create();