Switch team invites to email-only flow via identity API.
Deploy Ladill Care / deploy (push) Successful in 25s

Replace public ID member form with email invites, SSO provisioning, and
post-auth redirect for pending team access.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-01 06:45:36 +00:00
co-authored by Cursor
parent 7663fd49f4
commit 30ba94052e
6 changed files with 218 additions and 23 deletions
@@ -4,6 +4,8 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Services\Care\TeamMemberProvisioner;
use App\Services\Identity\IdentityTeamClient;
use Illuminate\Http\Client\Response as HttpResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
@@ -26,12 +28,14 @@ class SsoLoginController extends Controller
*/
private const MAX_SSO_ATTEMPTS = 3;
public function connect(Request $request): RedirectResponse|View
public function connect(Request $request, IdentityTeamClient $identity): RedirectResponse|View
{
$intended = (string) $request->query('redirect', route('care.dashboard'));
if (Auth::check()) {
return $this->safeRedirect($intended, route('care.dashboard'));
$redirect = $this->resolveLanding($identity, $request->user(), $intended);
return $this->safeRedirect($redirect, route('care.dashboard'));
}
if (! $request->boolean('fallback')) {
@@ -39,7 +43,10 @@ class SsoLoginController extends Controller
}
if ($this->attemptSilentRefresh($request, $intended)) {
return $this->safeRedirect($intended, route('care.dashboard'));
app(TeamMemberProvisioner::class)->sync(Auth::user());
$redirect = $this->resolveLanding($identity, Auth::user(), $intended);
return $this->safeRedirect($redirect, route('care.dashboard'));
}
$verifier = Str::random(64);
@@ -115,7 +122,9 @@ class SsoLoginController extends Controller
$request->session()->regenerate();
$request->session()->forget('sso.attempts');
return $this->finishCallback($request, $intended, null);
app(TeamMemberProvisioner::class)->sync($user);
return $this->finishCallback($request, $intended, null, app(IdentityTeamClient::class));
}
public function failed(Request $request): View
@@ -241,8 +250,12 @@ class SsoLoginController extends Controller
);
}
private function finishCallback(Request $request, string $intended, ?string $error = null): RedirectResponse
{
private function finishCallback(
Request $request,
string $intended,
?string $error = null,
?IdentityTeamClient $identity = null,
): RedirectResponse {
if ($error) {
$attempts = (int) $request->session()->get('sso.attempts', 0) + 1;
@@ -262,7 +275,21 @@ class SsoLoginController extends Controller
]);
}
return $this->safeRedirect($intended, route('care.dashboard'));
$user = Auth::user();
$redirect = ($user instanceof User && $identity)
? $this->resolveLanding($identity, $user, $intended)
: $intended;
return $this->safeRedirect($redirect, route('care.dashboard'));
}
private function resolveLanding(IdentityTeamClient $identity, User $user, string $intended): string
{
try {
return $identity->postAuthRedirect($user->ownerRef(), $intended);
} catch (\Throwable) {
return $intended;
}
}
private function safeReturnUrl(string $url): string