nhance/app/Helpers/NhanceWelnessSsoHelper.php

410 lines
14 KiB
PHP

<?php
namespace App\Helpers;
/**
* Nhance SSO Helper for CodeIgniter 4
*
* Usage:
* - Place this file in app/Helpers/nhance_sso_helper.php
* - Load helper: helper('nhance_sso');
*
* Functions:
* - generate_nhance_sso_url($userParams = null)
* - decrypt_nhance_sso_params($encryptedParams = null)
* - test_nhance_sso_encryption()
*/
if (!function_exists('generate_nhance_sso_url')) {
/**
* Generate Nhance SSO URL with encrypted parameters
*
* @param array|null $userParams User parameters array, uses sample data if null
* @return string Generated SSO URL
*/
function generate_nhance_sso_url($userParams = null) {
$helper = new NhanceSsoHelper();
return $helper->generateSSOUrl($userParams);
}
}
if (!function_exists('decrypt_nhance_sso_params')) {
/**
* Decrypt Nhance SSO parameters for testing
*
* @param string|null $encryptedParams Encrypted parameters, uses sample if null
* @return array Decrypted user parameters
*/
function decrypt_nhance_sso_params($encryptedParams = null) {
$helper = new NhanceSsoHelper();
return $helper->decryptUserParams($encryptedParams);
}
}
if (!function_exists('test_nhance_sso_encryption')) {
/**
* Test Nhance SSO encryption/decryption functionality
*
* @return array Test results
*/
function test_nhance_sso_encryption() {
$helper = new NhanceSsoHelper();
return $helper->runTests();
}
}
/**
* Nhance SSO Helper Class
*/
class NhanceWelnessSsoHelper {
private static $baseUrl = 'https://web.samuraijack.xyz/sso';
private static $clientId = 'nhance-gt-2tx7';
private static $encryptionKey = '32D1D5535157AF3D4667ADAB0CC795D77D022BB281AD3272EB134C72BD0B185E';
private static $algorithm = 'aes-256-cbc';
/**
* Get sample user parameters
*/
private static function getSampleUserParams() {
return [
'name' => 'John Doe 3',
'email' => 'john.doe3@email.com',
'memberId' => 'TEST-REL-01',
'gender' => 'Male',
'dob' => '1997-01-01',
'policyName' => 'Nhance DEMO',
'phone' => '6676126763',
'employeeId' => 'EMP-NHANCE-TEST-03',
'policyNumber' => "EMP-NHANCE-TEST-03",
'policyStartDate' => '2025-09-08',
'policyEndDate' => '2026-09-08',
'moduleName' => 'home',
'relation' => 'self',
'planId' => 'NHANCE-PLAN-1',
];
}
/**
* Get sample encrypted parameters for testing
*/
private static function getSampleEncryptedParams() {
// Generate sample encrypted params using sample data
$sampleParams = (SELF::getSampleUserParams());
return SELF::encryptUserParams($sampleParams);
}
/**
* Encrypt user parameters using AES-256-CBC
*/
private static function encryptUserParams($userParams) {
try {
// $jsonData = json_encode($userParams);
// // Generate a random IV
// $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length(SELF::$algorithm));
// // $iv = 'getvisitappdotcom';
// // Convert hex key to binary
// $key = hex2bin(SELF::$encryptionKey);
// // $key = (SELF::$encryptionKey);
// // Encrypt the data
// $encrypted = openssl_encrypt($jsonData, SELF::$algorithm, $key, 0, $iv);
// if ($encrypted === false) {
// throw new Exception("Encryption failed");
// }
// // Combine IV and encrypted data, then encode
// $encryptedData = base64_encode($iv . base64_decode($encrypted));
// // Make URL safe
// return str_replace(['+', '/', '='], ['-', '_', ''], $encryptedData);
$key = "getvisitappdotcom";
// Step 1: Build plaintext exactly like Node (raw join with '&')
$str = '';
foreach ($userParams as $k => $v) {
$str .= '&' . $k . '=' . $v;
}
$plainText = substr($str, 1); // remove leading &
// Step 2: Derive 32-byte key with SHA256
$sha256Key = hash('sha256', $key, true);
// Step 3: Fixed IV
$iv = "getvisitappdocom"; // 16 bytes
// Step 4: Encrypt
$cipherRaw = openssl_encrypt(
$plainText,
'aes-256-cbc',
$sha256Key,
OPENSSL_RAW_DATA,
$iv
);
// Step 5: base64url encode
return rtrim(strtr(base64_encode($cipherRaw), '+/', '-_'), '=');
} catch (Exception $e) {
log_message('error', 'Nhance SSO Encryption Error: ' . $e->getMessage());
throw new Exception("Encryption failed: " . $e->getMessage());
}
}
/**
* Decrypt user parameters for testing purposes
*/
public static function decryptUserParams($encryptedParams = null) {
try {
// Use sample encrypted params if none provided
if ($encryptedParams === null) {
$encryptedParams = SELF::getSampleEncryptedParams();
log_message('info', 'Using sample encrypted parameters for decryption test');
}
// Handle URL format if full URL is passed
if (strpos($encryptedParams, 'userParams=') !== false) {
$encryptedParams = SELF::extractParamsFromUrl($encryptedParams);
}
// Make URL-safe characters back to base64
$encryptedParams = str_replace(['-', '_'], ['+', '/'], $encryptedParams);
// Add padding if needed
$encryptedParams = $encryptedParams . str_repeat('=', (4 - strlen($encryptedParams) % 4) % 4);
// Decode base64
$data = base64_decode($encryptedParams);
if ($data === false) {
throw new Exception("Failed to decode base64 data");
}
// Extract IV and encrypted data
$ivLength = openssl_cipher_iv_length(SELF::$algorithm);
$iv = substr($data, 0, $ivLength);
$encrypted = base64_encode(substr($data, $ivLength));
// Convert hex key to binary
$key = hex2bin(SELF::$encryptionKey);
// Decrypt the data
$decrypted = openssl_decrypt($encrypted, SELF::$algorithm, $key, 0, $iv);
if ($decrypted === false) {
throw new Exception("Decryption failed");
}
// Decode JSON
$userParams = json_decode($decrypted, true);
if ($userParams === null) {
throw new Exception("Failed to decode JSON data");
}
return $userParams;
} catch (Exception $e) {
log_message('error', 'Nhance SSO Decryption Error: ' . $e->getMessage());
throw new Exception("Decryption error: " . $e->getMessage());
}
}
/**
* Generate SSO URL with encrypted parameters
*/
public static function generateSSOUrl($userParams = null) {
try {
// Use sample parameters if none provided
if ($userParams === null) {
$userParams = SELF::getSampleUserParams();
log_message('info', 'Using sample user parameters for SSO URL generation');
}
// Validate required parameters
SELF::validateUserParams($userParams);
// Encrypt user parameters
$encryptedParams = SELF::encryptUserParams($userParams);
// Build the SSO URL
$ssoUrl = SELF::$baseUrl . '?userParams=' . $encryptedParams . '&clientId=' . SELF::$clientId;
log_message('info', 'Nhance SSO URL generated successfully for user: ' . $userParams['email']);
return $ssoUrl;
} catch (Exception $e) {
log_message('error', 'Nhance SSO URL Generation Error: ' . $e->getMessage());
throw new Exception("Failed to generate SSO URL: " . $e->getMessage());
}
}
/**
* Validate user parameters
*/
private static function validateUserParams($userParams) {
$requiredFields = [
'name', 'email', 'phone', 'memberId', 'gender', 'dob',
'policyName', 'policyNumber', 'employeeId', 'moduleName',
'relation', 'planId', 'policyStartDate', 'policyEndDate'
];
foreach ($requiredFields as $field) {
if (!isset($userParams[$field]) || empty($userParams[$field])) {
throw new Exception("Required field '$field' is missing or empty");
}
}
// Validate date formats
if (!SELF::validateDate($userParams['dob']) ||
!SELF::validateDate($userParams['policyStartDate']) ||
!SELF::validateDate($userParams['policyEndDate'])) {
throw new Exception("Invalid date format. Use YYYY-MM-DD format");
}
// Validate gender
if (!in_array($userParams['gender'], ['Male', 'Female'])) {
throw new Exception("Gender must be 'Male' or 'Female'");
}
// Validate email
if (!filter_var($userParams['email'], FILTER_VALIDATE_EMAIL)) {
throw new Exception("Invalid email format");
}
}
/**
* Validate date format (YYYY-MM-DD)
*/
private static function validateDate($date) {
$d = \DateTime::createFromFormat('Y-m-d', $date);
return $d && $d->format('Y-m-d') === $date;
}
/**
* Extract encrypted parameters from SSO URL
*/
private static function extractParamsFromUrl($ssoUrl) {
$parsedUrl = parse_url($ssoUrl);
if (!isset($parsedUrl['query'])) {
throw new Exception("No query parameters found in URL");
}
parse_str($parsedUrl['query'], $queryParams);
if (!isset($queryParams['userParams'])) {
throw new Exception("userParams not found in URL");
}
return $queryParams['userParams'];
}
/**
* Run comprehensive tests
*/
public static function runTests() {
$results = [
'tests_passed' => 0,
'tests_failed' => 0,
'test_details' => []
];
try {
// Test 1: Sample data encryption/decryption
log_message('info', 'Running Nhance SSO Test 1: Sample data round-trip');
$sampleParams = SELF::getSampleUserParams();
$ssoUrl = SELF::generateSSOUrl($sampleParams);
$encryptedParams = SELF::extractParamsFromUrl($ssoUrl);
$decryptedParams = SELF::decryptUserParams($encryptedParams);
$test1Pass = json_encode($sampleParams) === json_encode($decryptedParams);
$results['test_details']['sample_round_trip'] = [
'status' => $test1Pass ? 'PASSED' : 'FAILED',
'original_params' => $sampleParams,
'decrypted_params' => $decryptedParams,
'sso_url' => $ssoUrl
];
if ($test1Pass) {
$results['tests_passed']++;
} else {
$results['tests_failed']++;
}
// Test 2: Custom parameters
log_message('info', 'Running Nhance SSO Test 2: Custom parameters');
$customParams = [
'name' => 'Jane Smith Test',
'email' => 'jane.test@example.com',
'phone' => '1122334455',
'memberId' => 'TEST-CUSTOM-001',
'gender' => 'Female',
'dob' => '1985-03-20',
'policyName' => 'Custom Test Policy',
'policyNumber' => 'CUSTOM-POL-001',
'employeeId' => 'EMP-CUSTOM-001',
'moduleName' => 'home',
'relation' => 'self',
'planId' => 'NHANCE-PLAN-1',
'policyStartDate' => date('Y-m-d'),
'policyEndDate' => date('Y-m-d', strtotime('+2 years'))
];
$customSsoUrl = SELF::generateSSOUrl($customParams);
$customEncryptedParams = SELF::extractParamsFromUrl($customSsoUrl);
$customDecryptedParams = SELF::decryptUserParams($customEncryptedParams);
$test2Pass = json_encode($customParams) === json_encode($customDecryptedParams);
$results['test_details']['custom_round_trip'] = [
'status' => $test2Pass ? 'PASSED' : 'FAILED',
'original_params' => $customParams,
'decrypted_params' => $customDecryptedParams,
'sso_url' => $customSsoUrl
];
if ($test2Pass) {
$results['tests_passed']++;
} else {
$results['tests_failed']++;
}
// Test 3: Null parameter handling
log_message('info', 'Running Nhance SSO Test 3: Null parameter handling');
$nullTestUrl = SELF::generateSSOUrl(null);
$nullDecrypted = SELF::decryptUserParams(null);
$test3Pass = !empty($nullTestUrl) && !empty($nullDecrypted);
$results['test_details']['null_parameter_handling'] = [
'status' => $test3Pass ? 'PASSED' : 'FAILED',
'generated_url' => $nullTestUrl,
'decrypted_sample' => $nullDecrypted
];
if ($test3Pass) {
$results['tests_passed']++;
} else {
$results['tests_failed']++;
}
} catch (Exception $e) {
$results['tests_failed']++;
$results['test_details']['error'] = $e->getMessage();
log_message('error', 'Nhance SSO Test Error: ' . $e->getMessage());
}
$results['overall_status'] = $results['tests_failed'] === 0 ? 'ALL_PASSED' : 'SOME_FAILED';
log_message('info', 'Nhance SSO Tests completed. Passed: ' . $results['tests_passed'] . ', Failed: ' . $results['tests_failed']);
return $results;
}
}
?>