SAMUL : GWM

This commit is contained in:
Gowtham M 2026-04-21 15:30:15 +05:30
parent d6b6c3a698
commit 4904dc6bd7
2 changed files with 229 additions and 31 deletions

View File

@ -3,7 +3,8 @@
namespace App\Controllers; namespace App\Controllers;
use App\Models\SamlClientModel; use App\Models\SamlClientModel;
use App\Models\UserModel; use App\Helpers\JWTToken;
use App\Helpers\RestAuthHelper;
use OneLogin\Saml2\Auth as SamlAuth; use OneLogin\Saml2\Auth as SamlAuth;
use OneLogin\Saml2\Error as SamlError; use OneLogin\Saml2\Error as SamlError;
use OneLogin\Saml2\Settings as SamlSettings; use OneLogin\Saml2\Settings as SamlSettings;
@ -86,55 +87,151 @@ class SamlController extends BaseController
public function acs() public function acs()
{ {
try { try {
$clientId = $this->request->getGet('client_id'); $postedEmail = $this->extractEmailFromPostedSamlResponse();
if (! $clientId) { if (! $postedEmail) {
return $this->response->setStatusCode(400)->setBody('Client ID required'); return $this->redirectToFrontendSso([
'status' => 'failed',
'code' => 400,
'data' => '',
'post_enrollment' => ['status' => 'failed', 'code' => 404, 'data' => ''],
'message' => 'Unable to resolve email from SAML response',
]);
} }
$at = strrchr($postedEmail, '@');
if ($at === false) {
return $this->redirectToFrontendSso([
'status' => 'failed',
'code' => 400,
'data' => '',
'post_enrollment' => ['status' => 'failed', 'code' => 404, 'data' => ''],
'message' => 'Invalid email in SAML response',
]);
}
$domain = strtolower(substr($at, 1));
$model = new SamlClientModel();
$client = $model->getByDomain($domain);
if (! $client) {
return $this->redirectToFrontendSso([
'status' => 'failed',
'code' => 404,
'data' => '',
'post_enrollment' => ['status' => 'failed', 'code' => 404, 'data' => ''],
'message' => 'SAML not configured for this domain',
]);
}
$clientId = $client['id'];
$auth = $this->getSamlAuth($clientId); $auth = $this->getSamlAuth($clientId);
} catch (\Throwable $e) {
return redirect()->to(site_url('login'))->with('error', $e->getMessage());
}
$auth->processResponse(); $auth->processResponse();
} catch (\Throwable $e) {
return $this->redirectToFrontendSso([
'status' => 'failed',
'code' => 500,
'data' => '',
'post_enrollment' => ['status' => 'failed', 'code' => 404, 'data' => ''],
'message' => $e->getMessage(),
]);
}
if (! $auth->isAuthenticated()) { if (! $auth->isAuthenticated()) {
return $this->response->setJSON($auth->getErrors()); return $this->redirectToFrontendSso([
'status' => 'failed',
'code' => 401,
'data' => '',
'post_enrollment' => ['status' => 'failed', 'code' => 404, 'data' => ''],
'message' => implode(', ', $auth->getErrors()),
]);
} }
$attributes = $auth->getAttributes(); $attributes = $auth->getAttributes();
$nameId = $auth->getNameId(); $nameId = $auth->getNameId();
$email = $this->resolveEmailFromSaml($nameId, $attributes); $email = $this->resolveEmailFromSaml($nameId, $attributes);
$email = trim((string) $email);
$UserModel = new UserModel(); // Same email lookup path used in RestAuthenticationController::getVerifiedUserData()
$user = $UserModel->getUserByEmail($email); $empdata = RestAuthHelper::getPreAndPostDataByEmailOrMobile(['email_id' => $email]);
if (! empty($empdata['pre']['email_corporate'])) {
if (! $user || $user->is_active === '0') { $email = (string) $empdata['pre']['email_corporate'];
session()->remove('saml_client_id'); } elseif (! empty($empdata['post']['email_id'])) {
$email = (string) $empdata['post']['email_id'];
return redirect()->to(site_url('login'))->with('error', 'User not registered or inactive');
} }
$user_team = $UserModel->getUserTeamsByUserID($user->id); $postEnrollment = ['status' => 'failed', 'code' => 404, 'data' => ''];
if (! empty($empdata['post'])) {
session()->regenerate(true); $postData = $empdata['post'];
unset($postData['employee_id']);
$session_data = [ $postData['token_type'] = 'post';
'isLoggedIn' => true, $postEnrollment = [
'userid' => $user->id, 'status' => 'success',
'userData' => $user, 'code' => 200,
'userProfile' => null, 'data' => JWTToken::encode($postData),
'user_team' => $user_team,
'saml_name_id' => $nameId,
'saml_attrs' => $attributes,
]; ];
set_session_data($session_data); }
set_session_data(['fingerprint' => generateFingerprint()]);
$this->getUserDeviceInfo($user->id, 'NhanceUser'); if (empty($empdata)) {
return $this->redirectToFrontendSso([
'status' => 'failed',
'code' => 404,
'data' => '',
'post_enrollment' => $postEnrollment,
'message' => 'User not found',
]);
}
return redirect()->to(site_url('dashboard/view')); if (! empty($empdata['pre'])) {
$employeeData = $empdata['pre'];
unset($employeeData['employee_id']);
$employeeData['token_type'] = 'pre';
$result = JWTToken::encode($employeeData);
return $this->redirectToFrontendSso([
'status' => 'success',
'code' => 200,
'data' => $result,
'post_enrollment' => $postEnrollment,
]);
}
return $this->redirectToFrontendSso([
'status' => 'failed',
'code' => 404,
'data' => '',
'post_enrollment' => $postEnrollment,
'message' => 'Employee not found in pre-enrollment',
]);
}
private function redirectToFrontendSso(array $payload)
{
$feUrl = rtrim((string) env('fe_url'), '/');
if ($feUrl === '') {
$feUrl = rtrim((string) env('FE_URL'), '/');
}
$responsePayload = [
'status' => $payload['status'] ?? 'failed',
'code' => $payload['code'] ?? 500,
'data' => $payload['data'] ?? '',
'post_enrollment' => $payload['post_enrollment'] ?? ['status' => 'failed', 'code' => 404, 'data' => ''],
];
// dd($responsePayload);
if (! empty($payload['message'])) {
$responsePayload['message'] = $payload['message'];
}
$encodedPayload = base64_encode((string) json_encode($responsePayload));
$params = http_build_query([
'payload' => $encodedPayload,
]);
// dd($feUrl . '/sso-login?' . $params);
return redirect()->to($feUrl . '/sso-login?' . $params);
} }
protected function getUserDeviceInfo(int $userId, string $type_of_user): void protected function getUserDeviceInfo(int $userId, string $type_of_user): void
@ -183,6 +280,47 @@ class SamlController extends BaseController
return (string) $nameId; return (string) $nameId;
} }
private function extractEmailFromPostedSamlResponse(): ?string
{
$raw = $this->request->getPost('SAMLResponse');
if (! is_string($raw) || $raw === '') {
return null;
}
$decoded = base64_decode($raw, true);
if ($decoded === false || trim($decoded) === '') {
return null;
}
libxml_use_internal_errors(true);
$xml = simplexml_load_string($decoded);
if ($xml === false) {
return null;
}
$emailNodes = $xml->xpath("//*[local-name()='Attribute' and (@Name='email' or @Name='Email' or @Name='mail' or @Name='http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress' or @Name='http://schemas.microsoft.com/identity/claims/emailaddress')]/*[local-name()='AttributeValue']");
if (is_array($emailNodes)) {
foreach ($emailNodes as $node) {
$val = trim((string) $node);
if ($val !== '' && filter_var($val, FILTER_VALIDATE_EMAIL)) {
return $val;
}
}
}
$nameIdNodes = $xml->xpath("//*[local-name()='NameID']");
if (is_array($nameIdNodes)) {
foreach ($nameIdNodes as $node) {
$val = trim((string) $node);
if ($val !== '' && filter_var($val, FILTER_VALIDATE_EMAIL)) {
return $val;
}
}
}
return null;
}
public function logout() public function logout()
{ {
try { try {
@ -253,4 +391,64 @@ class SamlController extends BaseController
->setHeader('Content-Type', 'application/xml; charset=utf-8') ->setHeader('Content-Type', 'application/xml; charset=utf-8')
->setBody($metadata); ->setBody($metadata);
} }
// public function verifyMSAuthUser()
// {
// $code = $this->request->getVar('code');
// // echo $code;
// try {
// $token = $this->provider->getAccessToken('authorization_code', [
// 'code' => $code
// ]);
// $ownerDetails = $this->provider->getResourceOwner($token);
// $data = $ownerDetails->toArray();
// $name = $data['name'] ?? null;
// $email = $data['upn'] ?? $data['unique_name'] ?? null;
// $res = checkUserExist($name, $email);
// if($res['status'] == true)
// {
// $user = $res['data'];
// //get service for the organization
// $orgService = $this->organizationModel->find($user['org_id']);
// $user['service'] = json_decode($orgService['services_ids'],true);
// foreach ($user['service'] as $key => $value)
// {
// $serviceData = $this->serviceModel->find($value['service_id']);
// $user['service'][$key]['name'] = $serviceData['name'];
// $user['service'][$key]['icon'] = $serviceData['icon'];
// }
// //get role
// $user['role'] = $this->userModel->getRole($user['role_id']);
// //find user has the all access
// $user['plan_action'] = getUserPlanCreationRestrictionStatus($user);
// $token = generateJWT($user);
// return $this->respond([ 'status' => 200,'message' => 'Login successful','token' => $token ]);
// }else{
// return $this->respond([ 'status' => 401,'message' => 'Login Failed','data' => [] ]);
// }
// } catch (IdentityProviderException $e) {
// exit($e->getMessage());
// }
// }
//end of microsoft oAuth
} }

View File

@ -73,7 +73,7 @@ class MyGoogleDrive
} }
if (php_sapi_name() != 'cli') { if (php_sapi_name() != 'cli') {
throw new Exception('This application must be run on the command line.'); throw new \Exception('This application must be run on the command line.');
} }
$authUrl = $this->client->createAuthUrl(); $authUrl = $this->client->createAuthUrl();