query('redirect_uri', MobileAuthController::ALLOWED_REDIRECT_URIS[0]); abort_unless( in_array($redirectUri, MobileAuthController::ALLOWED_REDIRECT_URIS, true), 403, 'Invalid redirect_uri', ); $this->redirectUri = $redirectUri; $this->deviceName = str((string) request()->query('device_name', MobileAuthController::DEFAULT_DEVICE_NAME)) ->limit(64, '') ->whenEmpty(fn () => str(MobileAuthController::DEFAULT_DEVICE_NAME)) ->value(); // The completion controller reads the flow state from the session — // the wallet callback arrives outside this session, so it can't // carry the redirect target itself. session([ 'mobile_auth' => [ 'redirect_uri' => $this->redirectUri, 'device_name' => $this->deviceName, ], ]); if (auth()->check()) { return; } $this->initChallenge(); } /** * Generate a fresh k1 challenge for the LNURL flow. The Lightning * wallet signs it via LNURL-auth; the resulting LoginKey row is picked * up by checkAuth() below. */ protected function initChallenge(): void { $this->k1 = bin2hex(str()->random(32)); if (app()->environment('local')) { $url = 'https://mmy4dp8eab.sharedwithexpose.com/api/lnurl-auth-callback?tag=login&k1='.$this->k1.'&action=login'; } else { $url = url('/api/lnurl-auth-callback?tag=login&k1='.$this->k1.'&action=login'); } $this->lnurl = lnurl\encodeUrl($url); $image = 'public/img/domains/'.session('lang_country', 'de-DE').'.jpg'; if (! file_exists(base_path($image))) { $image = 'public/img/domains/de-DE.jpg'; } $this->qrCode = base64_encode(QrCode::format('png') ->size(300) ->merge('/'.$image, .3) ->errorCorrection('H') ->generate($this->lnurl)); } public function checkAuth(): void { $loginKey = LoginKey::query() ->where('k1', $this->k1) ->where('created_at', '>=', now()->subMinutes(5)) ->first(); if (! $loginKey) { return; } // Same handoff pattern as the desktop Lightning login: navigate via // the client instead of redirecting from inside wire:poll, so a // stray poll tick can't race the completion request. $this->dispatch( 'mobile-login-ready', url: route('auth.mobile.complete', ['k1' => $this->k1]), ); } public function resetAuth(): void { $this->initChallenge(); } public function switchAccount(): void { auth()->guard('web')->logout(); session()->invalidate(); session()->regenerateToken(); $this->redirect(route('auth.mobile', [ 'redirect_uri' => $this->redirectUri, 'device_name' => $this->deviceName, ])); } }; ?>