Files
einundzwanzig-verein/app/Auth/NostrSessionGuard.php
T
HolgerHatGarKeineNode 6bb7d93d1d feat(auth): require signed NIP-42 event for Nostr login
Closes a security flaw where the server trusted any pubkey the client
sent. The frontend now signs a per-session, time-bound challenge
(kind-22242 event) that the backend verifies with swentel/nostr-php
before establishing the session.

- NostrAuth: issueChallenge() + loginWithSignedEvent() with full
  schnorr/id verification, TTL window, and idempotent re-entry for
  concurrent Livewire listeners.
- auth-button: mounts a fresh challenge, exposes it via data-attribute
  + requestNostrChallenge() fallback, renders a full-viewport AAA-style
  loading overlay while the wallet signs.
- NostrSessionGuard: override logout() to drop the cookie-jar dep so
  programmatic logout works in any context.
2026-05-20 01:09:20 +02:00

55 lines
1.2 KiB
PHP

<?php
namespace App\Auth;
use Illuminate\Auth\SessionGuard;
use Illuminate\Contracts\Auth\Authenticatable;
class NostrSessionGuard extends SessionGuard
{
public function loginByPubkey(string $pubkey): void
{
$user = new NostrUser($pubkey);
$this->updateSession($user->getAuthIdentifier());
$this->setUser($user);
$this->fireLoginEvent($user, false);
}
protected function updateSession($id): void
{
$this->session->put($this->getName(), $id);
$this->session->migrate(true);
}
public function user(): ?Authenticatable
{
if ($this->user !== null) {
return $this->user;
}
$id = $this->session->get($this->getName());
if ($id !== null) {
$this->user = $this->provider->retrieveById($id);
}
return $this->user;
}
/**
* Nostr auth has no remember-me cookie, so we override the parent's
* cookie-clearing logout to avoid CookieJar dependencies in code paths
* (e.g. tests) where the cookie jar isn't bound.
*/
public function logout(): void
{
$this->session->remove($this->getName());
$this->user = null;
$this->loggedOut = true;
}
}