handleCallback(); } catch (SasslyAuthException $e) { $back = $e->returnTo ?? $paths['home']; if ($e->reason === 'authorize_error' && $e->oauthError === 'login_required') { // prompt=none found no Sassly session: show the page as a guest. header('Location: ' . $back, true, 302); exit; } error_log('[sassly-auth] callback failed: ' . $e->reason . ' - ' . $e->getMessage()); $message = match (true) { $e->reason === 'authorize_error' && $e->oauthError === 'access_denied' => 'Login dibatalkan.', in_array($e->reason, ['state_missing', 'state_mismatch'], true) => 'Sesi login sudah kedaluwarsa atau dibuka dari tab lain.', in_array($e->reason, ['network_error', 'server_error', 'jwks_unavailable'], true) => 'Layanan login sedang tidak bisa dihubungi. Coba beberapa saat lagi.', default => 'Login gagal (' . $e->reason . ').', }; sassly_render_page(400, 'Login gagal', $message, false, $paths['login'] . '?return_to=' . rawurlencode($back)); exit; } $users = sassly_find_or_link_users($identity); if (count($users) === 0) { // Not registered (or disabled) in this app. No local session is started. $_SESSION['sassly_denied_hint'] = $identity['tokens']['id_token']; // lets "Keluar / ganti akun" skip the confirm screen $who = $identity['email'] ?? 'ini'; // The Sassly ID lets an admin link the user manually (needed when email_verified is false). sassly_render_page(403, 'Akun belum terdaftar', "Akun $who belum terdaftar atau tidak aktif di aplikasi ini. Hubungi admin dan sebutkan ID akun Sassly: {$identity['sub']}. Atau keluar lalu masuk dengan akun lain.", true); exit; } if (count($users) > 1) { // Same person in several tenants/workspaces: let them choose. $_SESSION['sassly_choose'] = [ 'identity' => $identity, 'user_ids' => array_map(static fn(array $u): string => (string)$u['id'], $users), 'at' => time(), ]; header('Location: ' . $paths['choose'], true, 302); exit; } sassly_complete_login($identity, $users[0]);