- R-01: ApiNewsroomAssignment hängt an eine bestehende Firma nur noch Owner, Mitglieder oder Nutzer aus NEWSROOM_API_ASSIGNMENT_USER_IDS; Pivot mit granted_via = api; Befehl company-memberships:api-assignments (Liste, --remove mit Vorschau) - K-04: OAuth-Verifikation eines offenen Kontos verwirft Passwort, remember_token und Sanctum-Tokens; SessionRevocation + Middleware EnsureSessionIsNotRevoked widerruft alte Sessions (Redis-tauglich) - K-08: LoginCompletion für Passwort, Magic Link und Google — last_login_at und Anmeldemethode auch nach 2FA, Landeziel über die Challenge, Google ohne erzwungenes remember, magic-login ohne guest für eigene Links - B-10: eigener Magic-Link-Zweck image_confirmation (Migration) - K-07: legalAcceptanceVersions #[Locked], Versionswechsel beim Absenden wird abgelehnt, Gate-Abfragen je Request zwischengespeichert Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
68 lines
2.3 KiB
PHP
68 lines
2.3 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Controllers\Auth;
|
||
|
||
use App\Http\Controllers\Controller;
|
||
use App\Services\Auth\LoginCompletion;
|
||
use App\Services\Auth\SocialAuthService;
|
||
use App\Support\LoginRedirect;
|
||
use Illuminate\Http\RedirectResponse;
|
||
use Illuminate\Http\Request;
|
||
use Laravel\Socialite\Facades\Socialite;
|
||
|
||
/**
|
||
* Google-Login (WS-6). Erst-Login legt – de-dupliziert über die E-Mail – einen
|
||
* aktiven, verifizierten customer-Account an; bestehende Accounts werden nur
|
||
* verknüpft. Deaktivierte Accounts werden nicht reaktiviert.
|
||
*/
|
||
class GoogleController extends Controller
|
||
{
|
||
public function redirect(): RedirectResponse
|
||
{
|
||
return Socialite::driver('google')->redirect();
|
||
}
|
||
|
||
public function callback(Request $request, SocialAuthService $social, LoginCompletion $completion): RedirectResponse
|
||
{
|
||
try {
|
||
$googleUser = Socialite::driver('google')->user();
|
||
} catch (\Throwable) {
|
||
return redirect()->route('login')->withErrors([
|
||
'email' => __('Die Anmeldung mit Google ist fehlgeschlagen. Bitte versuchen Sie es erneut.'),
|
||
]);
|
||
}
|
||
|
||
$user = $social->resolveUser(
|
||
'google',
|
||
(string) $googleUser->getId(),
|
||
$googleUser->getEmail(),
|
||
$googleUser->getName(),
|
||
);
|
||
|
||
if (! $user || ! $user->is_active) {
|
||
return redirect()->route('login')->withErrors([
|
||
'email' => __('Ihr Konto ist nicht aktiv. Bitte wenden Sie sich an den Support.'),
|
||
]);
|
||
}
|
||
|
||
// 2FA aktiv: wie Passwort- und Magic-Link-Login nicht direkt einloggen,
|
||
// sondern in Fortifys Challenge übergeben (Audit F02). Google belegt
|
||
// den Besitz des Postfachs, nicht den zweiten Faktor.
|
||
//
|
||
// Kein erzwungenes „Angemeldet bleiben" mehr (Audit K-08): wie beim
|
||
// Magic Link nur die Sitzung, siehe LoginCompletion.
|
||
if ($user->hasEnabledTwoFactorAuthentication()) {
|
||
$completion->handOffToTwoFactor($request, $user, 'google');
|
||
|
||
return redirect()->route('two-factor.challenge');
|
||
}
|
||
|
||
$completion->login($request, $user, 'google');
|
||
|
||
return redirect(LoginRedirect::safeTarget(
|
||
$user,
|
||
$request->session()->pull('url.intended'),
|
||
LoginRedirect::homeFor($user),
|
||
));
|
||
}
|
||
}
|