implement crm login

This commit is contained in:
subhajit 2026-07-16 17:42:04 +05:30
parent 462762a13f
commit 0efd443a53
4 changed files with 99 additions and 3 deletions

View File

@ -40,10 +40,14 @@ public function launchSSO($id)
return redirect()->route('dashboard')->with('error', 'Access denied. You do not have permission to access this service.'); return redirect()->route('dashboard')->with('error', 'Access denied. You do not have permission to access this service.');
} }
$url = $app->url;
if (str_contains(strtolower($url), 'convexcrm.convexsol.co')) {
$url = rtrim($url, '/') . '/admin/authentication/microsoft_login';
}
if ($user->microsoft_id) { if ($user->microsoft_id) {
// Save target app URL in session so callback knows where to redirect // Save target app URL in session so callback knows where to redirect
session(['sso_target_url' => $app->url]); session(['sso_target_url' => $url]);
try { try {
// Determine domain hint based on user's email domain to skip account type prompt // Determine domain hint based on user's email domain to skip account type prompt
@ -242,4 +246,45 @@ public function destroyPersonalApp($id)
return redirect()->route('dashboard')->with('success', 'Custom app deleted successfully.'); return redirect()->route('dashboard')->with('success', 'Custom app deleted successfully.');
} }
/**
* Launch a personal app using SSO.
*/
public function launchPersonalSSO($id)
{
$user = Auth::user();
$pApp = $user->personalApps()->findOrFail($id);
$url = $pApp->url;
if (str_contains(strtolower($url), 'convexcrm.convexsol.co')) {
$url = rtrim($url, '/') . '/admin/authentication/microsoft_login';
}
if ($user->microsoft_id) {
// Save target app URL in session so callback knows where to redirect
session(['sso_target_url' => $url]);
try {
// Determine domain hint based on user's email domain to skip account type prompt
$domainHint = (str_ends_with($user->email, '.onmicrosoft.com') || (str_contains($user->email, '@') && !str_ends_with($user->email, 'outlook.com') && !str_ends_with($user->email, 'hotmail.com') && !str_ends_with($user->email, 'live.com')))
? 'organizations'
: 'consumers';
// Redirect to Microsoft OAuth authorize page with login_hint, domain_hint, prompt=none and custom callback
return Socialite::driver('microsoft')
->redirectUrl(route('sso.callback'))
->with([
'login_hint' => $user->email,
'domain_hint' => $domainHint,
'prompt' => 'none'
])
->redirect();
} catch (\Exception $e) {
return redirect($url);
}
}
// For non-Microsoft or non-Microsoft-linked users, redirect directly
return redirect($url);
}
} }

View File

@ -862,7 +862,7 @@
</div> </div>
<!-- Logo Wrapper --> <!-- Logo Wrapper -->
<div class="service-logo-wrapper" onclick="window.open('{{ $pApp->url }}', '_blank')"> <div class="service-logo-wrapper" onclick="launchSSO('{{ $pApp->name }}', '{{ route('sso.personal-launch', $pApp->id) }}')">
@if($pApp->logo) @if($pApp->logo)
<img src="{{ asset($pApp->logo) }}" alt="{{ $pApp->name }}" class="service-logo-img"> <img src="{{ asset($pApp->logo) }}" alt="{{ $pApp->name }}" class="service-logo-img">
@else @else
@ -874,7 +874,7 @@
</div> </div>
<!-- Name --> <!-- Name -->
<h3 class="service-title" onclick="window.open('{{ $pApp->url }}', '_blank')">{{ strtoupper($pApp->name) }}</h3> <h3 class="service-title" onclick="launchSSO('{{ $pApp->name }}', '{{ route('sso.personal-launch', $pApp->id) }}')">{{ strtoupper($pApp->name) }}</h3>
@if($pApp->tag) @if($pApp->tag)
<div style="font-size: 0.65rem; color: var(--text-muted); text-transform: uppercase; margin-top: 4px; letter-spacing: 0.5px;">{{ $pApp->tag }}</div> <div style="font-size: 0.65rem; color: var(--text-muted); text-transform: uppercase; margin-top: 4px; letter-spacing: 0.5px;">{{ $pApp->tag }}</div>
@endif @endif

View File

@ -25,6 +25,7 @@
Route::middleware(['auth', 'role:user'])->group(function () { Route::middleware(['auth', 'role:user'])->group(function () {
Route::get('/sso/launch/{id}', [DashboardController::class, 'launchSSO'])->name('sso.launch'); Route::get('/sso/launch/{id}', [DashboardController::class, 'launchSSO'])->name('sso.launch');
Route::get('/sso/personal-launch/{id}', [DashboardController::class, 'launchPersonalSSO'])->name('sso.personal-launch');
Route::get('/sso/callback', [DashboardController::class, 'handleSSOCallback'])->name('sso.callback'); Route::get('/sso/callback', [DashboardController::class, 'handleSSOCallback'])->name('sso.callback');
Route::get('/sso/launch-app', [DashboardController::class, 'launchApp'])->name('sso.launch-app'); Route::get('/sso/launch-app', [DashboardController::class, 'launchApp'])->name('sso.launch-app');

View File

@ -517,4 +517,54 @@ public function test_user_personal_custom_apps(): void
'id' => $personalApp->id 'id' => $personalApp->id
]); ]);
} }
/**
* Test silent Microsoft SSO redirection for Convex CRM.
*/
public function test_convexcrm_silent_sso_redirection(): void
{
$user = User::create([
'name' => 'Convex CRM User',
'email' => 'convexcrm@sentientgeeks.com',
'role' => 'user',
'microsoft_id' => 'mock-ms-id-777',
]);
$app = \App\Models\App::create([
'name' => 'Convex CRM',
'url' => 'https://demo-convexcrm.convexsol.co/',
'color' => '#123456',
'tag' => 'CRM'
]);
// Enable access to this app
$devRole = Role::firstOrCreate(['name' => 'Developer'], ['description' => 'Developer role']);
$devRole->apps()->syncWithoutDetaching([$app->id]);
$user->roles()->syncWithoutDetaching([$devRole->id]);
// Trigger SSO launch for corporate app
$response = $this->actingAs($user)
->get(route('sso.launch', $app->id));
// It should initiate Microsoft OAuth redirect to refresh the session
// And save rewritten target URL (Convex CRM Microsoft login redirect endpoint) in session
$this->assertEquals(
'https://demo-convexcrm.convexsol.co/admin/authentication/microsoft_login',
session('sso_target_url')
);
// Test personal custom app version
$pApp = $user->personalApps()->create([
'name' => 'My Custom Convex',
'url' => 'https://demo-convexcrm.convexsol.co',
]);
$responsePersonal = $this->actingAs($user)
->get(route('sso.personal-launch', $pApp->id));
$this->assertEquals(
'https://demo-convexcrm.convexsol.co/admin/authentication/microsoft_login',
session('sso_target_url')
);
}
} }