subhajit_changes_06_07 #9
@ -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.');
|
||||
}
|
||||
|
||||
$url = $app->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' => $app->url]);
|
||||
session(['sso_target_url' => $url]);
|
||||
|
||||
try {
|
||||
// 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.');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -862,7 +862,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 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)
|
||||
<img src="{{ asset($pApp->logo) }}" alt="{{ $pApp->name }}" class="service-logo-img">
|
||||
@else
|
||||
@ -874,7 +874,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 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)
|
||||
<div style="font-size: 0.65rem; color: var(--text-muted); text-transform: uppercase; margin-top: 4px; letter-spacing: 0.5px;">{{ $pApp->tag }}</div>
|
||||
@endif
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
Route::middleware(['auth', 'role:user'])->group(function () {
|
||||
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/launch-app', [DashboardController::class, 'launchApp'])->name('sso.launch-app');
|
||||
|
||||
|
||||
@ -517,4 +517,54 @@ public function test_user_personal_custom_apps(): void
|
||||
'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')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user