diff --git a/php_code/.env b/php_code/.env index 599be8f7..66ef4a66 100644 --- a/php_code/.env +++ b/php_code/.env @@ -7,10 +7,15 @@ LOG_CHANNEL=daily LUPMISAPIKEY=1c46538c712e9b5b MNOTOFYKEY=hFsiPMAPS3sIdwYSIthRO5JtS -DB_CONNECTION=mysql -DB_HOST=host.docker.internal +#DB_CONNECTION=mysql +#DB_HOST=host.docker.internal + +DB_CONNECTION=sqlite +#DB_DATABASE=database/lupmis.sqlite +DB_DATABASE=/var/www/html/database/lupmis.sqlite + DB_PORT=3306 -DB_DATABASE=lupmis +#DB_DATABASE=lupmis.sqlite DB_USERNAME=root DB_PASSWORD=p@ssw0rd @@ -19,6 +24,7 @@ CACHE_DRIVER=file QUEUE_CONNECTION=sync SESSION_DRIVER=file SESSION_LIFETIME=120 +SESSION_DOMAIN=.housebanson.net REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null diff --git a/php_code/app/Http/Controllers/Api/AuthController.php b/php_code/app/Http/Controllers/Api/AuthController.php new file mode 100644 index 00000000..2539a080 --- /dev/null +++ b/php_code/app/Http/Controllers/Api/AuthController.php @@ -0,0 +1,47 @@ +json([ + 'message' => 'Welcome to your Laravel 11 API!', + 'status' => 'success' + ], 200); + } + + // Generate token on login + public function login(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'password' => 'required', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user || !Hash::check($request->password, $user->password)) { + return response()->json([ + 'message' => 'Invalid credentials' + ], 401); + } + + // Generate the plain text token using Sanctum + $token = $user->createToken('auth_token')->plainTextToken; + + return response()->json([ + 'access_token' => $token, + 'token_type' => 'Bearer', + ], 200); + } +} + +?> \ No newline at end of file diff --git a/php_code/app/Http/Controllers/LandingpageController.php b/php_code/app/Http/Controllers/LandingpageController.php index d76a4266..155e4a13 100644 --- a/php_code/app/Http/Controllers/LandingpageController.php +++ b/php_code/app/Http/Controllers/LandingpageController.php @@ -12,7 +12,6 @@ class LandingpageController extends Controller $data = [ 'page_title' => 'Landing Page' ]; - // dump(session('current_user')); return view('landing', $data); } diff --git a/php_code/app/Http/Controllers/SsoController.php b/php_code/app/Http/Controllers/SsoController.php new file mode 100644 index 00000000..90396f27 --- /dev/null +++ b/php_code/app/Http/Controllers/SsoController.php @@ -0,0 +1,55 @@ +input('token'); + // dd(plainToken); + + \Log::info("New Request : $plainToken"); + + if (!$plainToken) { + return response()->json(['valid' => false], 400); + } + $hashedToken = hash('sha256', $plainToken); + \Log::info("hashed Token : $hashedToken"); + + + + $session = DB::table('sso_sessions')->where('token', $hashedToken)->first(); + \Log::info("session : " . json_encode($session)); + if ($session){ + $check_user_url = 'user_mgt/get_user_by_user_id.php'; + $data = ['user_id' => $session->user_id, 'api_token' => env('LUPMISAPIKEY')]; + + $check_user = ApiCalls::CurlPost(json_encode($data), $check_user_url); + if($check_user == false){ + \Log::info("User not found : $hashedToken"); + return response()->json(['valid' => false], 401); + } + $result = json_decode($check_user, true); + if($result['success'] == false){ + return response()->json(['valid' => false], 401); + } + // if($result['data']['is_disabled'] == true){ + // return response()->json(['valid 099' => false], 401); + // } + $logged_in = $result['data']; + return response()->json([ + 'valid' => true, + 'logged_in_user' => $logged_in + ], 200); + } + return response()->json(['valid 0123' => false], 401); +} +} diff --git a/php_code/app/Http/Controllers/UserloginController.php b/php_code/app/Http/Controllers/UserloginController.php index df36c7e5..727c2cf3 100644 --- a/php_code/app/Http/Controllers/UserloginController.php +++ b/php_code/app/Http/Controllers/UserloginController.php @@ -4,7 +4,9 @@ namespace App\Http\Controllers; use App\Utilities\ApiCalls; use Session; use Illuminate\Http\Request; - +use Illuminate\Support\Facades\Cookie; +use Illuminate\Support\Str; +use Illuminate\Support\Facades\DB; class UserloginController extends Controller { @@ -20,7 +22,8 @@ class UserloginController extends Controller $this->validate($request, ['username' => 'required', 'password' => 'required']); $logged_in = ''; - # call API here to login + + // dd(config('database.connections.sqlite.database')); $check_user_url = 'auth/auth_user.php'; $data = ['user' => $request->username, 'pass' => $request->password, 'api_token' => env('LUPMISAPIKEY')]; @@ -42,7 +45,6 @@ class UserloginController extends Controller "region_id":10, "district_id":122 } - */ @@ -57,6 +59,14 @@ class UserloginController extends Controller ##return redirect("user-login")->withErrors(array("Your Account has been disabled. Contact your administrator!"))->withInput(); } $logged_in = $result['data']; + $plainToken = Str::random(60); + + // $hashedToken = hash('sha256', $plainToken); + DB::table('sso_sessions')->insert([ + 'user_id' => $logged_in['user_id'], + 'token' => hash('sha256', $plainToken), + 'created_at' => now(), + ]); $request->session()->regenerate(true); $request->session()->put('current_user.ua_id', $logged_in['ua_id']); @@ -72,10 +82,12 @@ class UserloginController extends Controller $request->session()->put('current_user.region_id', $logged_in['region_id']); $request->session()->put('current_user.is_password_changed', $logged_in['is_password_changed']); $request->session()->put('current_user.district_id', $logged_in['district_id']); + // $request->session()->put('current_user.hashedToken', $hashedToken); + $request->session()->put('current_user.plainToken', $plainToken); + // $request->session()->put('current_user.permissions', $logged_in['permissions']); - - + Cookie::queue('sso_auth_token', $plainToken, 60, '/', '.lupmis4luspa.org'); \Log::info($logged_in['full_name']. ' Successfully logged in at : ' . date('Y-m-d H:i:s')); return redirect(url('/')); } @@ -83,6 +95,10 @@ class UserloginController extends Controller $user_id = session('current_user.id'); $username = session('current_user.name'); + $plainToken = request()->cookie('sso_auth_token'); + if ($plainToken) { + Cookie::queue(Cookie::forget('sso_auth_token', '/', '.lupmis4luspa.org')); + } $logout_user_url = 'auth/logout_user.php'; $data = ['user_id' => $user_id, 'api_token' => env('LUPMISAPIKEY')]; diff --git a/php_code/app/Models/User.php b/php_code/app/Models/User.php index 749c7b77..65642024 100644 --- a/php_code/app/Models/User.php +++ b/php_code/app/Models/User.php @@ -6,11 +6,13 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; +use Laravel\Sanctum\HasApiTokens; class User extends Authenticatable { /** @use HasFactory<\Database\Factories\UserFactory> */ use HasFactory, Notifiable; + use HasApiTokens; /** * The attributes that are mass assignable. diff --git a/php_code/bootstrap/app.php b/php_code/bootstrap/app.php index 7b162dac..f0cc75b1 100644 --- a/php_code/bootstrap/app.php +++ b/php_code/bootstrap/app.php @@ -7,11 +7,14 @@ use Illuminate\Foundation\Configuration\Middleware; return Application::configure(basePath: dirname(__DIR__)) ->withRouting( web: __DIR__.'/../routes/web.php', + api: __DIR__.'/../routes/api.php', commands: __DIR__.'/../routes/console.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware) { - // + $middleware->encryptCookies(except: [ + 'sso_auth_token', + ]); }) ->withExceptions(function (Exceptions $exceptions) { // diff --git a/php_code/composer.json b/php_code/composer.json index 8c07d8c9..3224c253 100644 --- a/php_code/composer.json +++ b/php_code/composer.json @@ -8,6 +8,7 @@ "require": { "php": "^8.2", "laravel/framework": "^11.31", + "laravel/sanctum": "^4.0", "laravel/tinker": "^2.9", "laravel/ui": "^4.6" }, diff --git a/php_code/composer.lock b/php_code/composer.lock index 3b697952..7485bc58 100644 --- a/php_code/composer.lock +++ b/php_code/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a7159c5237c3c2e75dbd1d23c85e732c", + "content-hash": "c48ad68828797abd55f721d8cceec781", "packages": [ { "name": "brick/math", @@ -1326,6 +1326,69 @@ }, "time": "2026-02-03T06:57:26+00:00" }, + { + "name": "laravel/sanctum", + "version": "v4.3.2", + "source": { + "type": "git", + "url": "https://github.com/laravel/sanctum.git", + "reference": "2a9bccc18e9907808e0018dd15fa643937886b1e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/2a9bccc18e9907808e0018dd15fa643937886b1e", + "reference": "2a9bccc18e9907808e0018dd15fa643937886b1e", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/console": "^11.0|^12.0|^13.0", + "illuminate/contracts": "^11.0|^12.0|^13.0", + "illuminate/database": "^11.0|^12.0|^13.0", + "illuminate/support": "^11.0|^12.0|^13.0", + "php": "^8.2", + "symfony/console": "^7.0|^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.6", + "orchestra/testbench": "^9.15|^10.8|^11.0", + "phpstan/phpstan": "^1.10" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Sanctum\\SanctumServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sanctum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.", + "keywords": [ + "auth", + "laravel", + "sanctum" + ], + "support": { + "issues": "https://github.com/laravel/sanctum/issues", + "source": "https://github.com/laravel/sanctum" + }, + "time": "2026-04-30T11:46:25+00:00" + }, { "name": "laravel/serializable-closure", "version": "v2.0.9", diff --git a/php_code/config/sanctum.php b/php_code/config/sanctum.php new file mode 100644 index 00000000..cde73cff --- /dev/null +++ b/php_code/config/sanctum.php @@ -0,0 +1,87 @@ + explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( + '%s%s', + 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', + Sanctum::currentApplicationUrlWithPort(), + // Sanctum::currentRequestHost(), + ))), + + /* + |-------------------------------------------------------------------------- + | Sanctum Guards + |-------------------------------------------------------------------------- + | + | This array contains the authentication guards that will be checked when + | Sanctum is trying to authenticate a request. If none of these guards + | are able to authenticate the request, Sanctum will use the bearer + | token that's present on an incoming request for authentication. + | + */ + + 'guard' => ['web'], + + /* + |-------------------------------------------------------------------------- + | Expiration Minutes + |-------------------------------------------------------------------------- + | + | This value controls the number of minutes until an issued token will be + | considered expired. This will override any values set in the token's + | "expires_at" attribute, but first-party sessions are not affected. + | + */ + + 'expiration' => null, + + /* + |-------------------------------------------------------------------------- + | Token Prefix + |-------------------------------------------------------------------------- + | + | Sanctum can prefix new tokens in order to take advantage of numerous + | security scanning initiatives maintained by open source platforms + | that notify developers if they commit tokens into repositories. + | + | See: https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning + | + */ + + 'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''), + + /* + |-------------------------------------------------------------------------- + | Sanctum Middleware + |-------------------------------------------------------------------------- + | + | When authenticating your first-party SPA with Sanctum you may need to + | customize some of the middleware Sanctum uses while processing the + | request. You may change the middleware listed below as required. + | + */ + + 'middleware' => [ + 'authenticate_session' => AuthenticateSession::class, + 'encrypt_cookies' => EncryptCookies::class, + 'validate_csrf_token' => ValidateCsrfToken::class, + ], + +]; diff --git a/php_code/database/migrations/2026_05_27_090302_create_personal_access_tokens_table.php b/php_code/database/migrations/2026_05_27_090302_create_personal_access_tokens_table.php new file mode 100644 index 00000000..40ff706e --- /dev/null +++ b/php_code/database/migrations/2026_05_27_090302_create_personal_access_tokens_table.php @@ -0,0 +1,33 @@ +id(); + $table->morphs('tokenable'); + $table->text('name'); + $table->string('token', 64)->unique(); + $table->text('abilities')->nullable(); + $table->timestamp('last_used_at')->nullable(); + $table->timestamp('expires_at')->nullable()->index(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('personal_access_tokens'); + } +}; diff --git a/php_code/lupmis b/php_code/lupmis new file mode 100644 index 00000000..19d45617 Binary files /dev/null and b/php_code/lupmis differ diff --git a/php_code/resources/views/landing.blade.php b/php_code/resources/views/landing.blade.php index 13c4cd41..4ce422c7 100644 --- a/php_code/resources/views/landing.blade.php +++ b/php_code/resources/views/landing.blade.php @@ -93,7 +93,8 @@