# SSO Integration Guide

Panduan menambahkan aplikasi Laravel yang sudah ada ke sistem **GMP Platform SSO**.

> Auth Server: `apps/auth` (port 8000)  
> Token: Laravel Sanctum  
> Middleware: `gmp/laravel-core` → `SsoMiddleware`

---

## Alur SSO

```
User buka /dashboard (app baru)
    └─ tidak ada session
        └─ redirect → localhost:8000/login?redirect_url=http://app-baru/dashboard
            └─ login berhasil
                └─ redirect → http://app-baru/dashboard?sso_token=xxx
                    └─ SsoMiddleware validasi token ke GET localhost:8000/api/user
                        └─ simpan ke session  →  masuk ✓
```

---

## Skenario A — App Laravel + Inertia/React (Rekomendasi)

### Langkah 1 — Pindahkan ke folder `apps/`

```
gmp_platform/
└── apps/
    └── nama-app/        ← taruh di sini
```

---

### Langkah 2 — Tambahkan `laravel-core` ke `composer.json`

```json
{
    "require": {
        "gmp/laravel-core": "@dev"
    },
    "repositories": [
        {
            "type": "path",
            "url": "../../packages/laravel-core",
            "options": { "symlink": true }
        }
    ],
    "minimum-stability": "dev",
    "prefer-stable": true
}
```

Lalu jalankan:

```bash
composer update gmp/laravel-core
```

---

### Langkah 3 — Buat `config/sso.php`

```php
<?php

return [
    'auth_url' => env('AUTH_APP_URL', 'http://localhost:8000'),
];
```

---

### Langkah 4 — Tambahkan ke `.env`

```env
AUTH_APP_URL=http://localhost:8000
```

> Ganti port sesuai environment (staging/production menggunakan domain, bukan port).

---

### Langkah 5 — Daftarkan middleware di `bootstrap/app.php`

```php
use Gmp\LaravelCore\Middleware\SsoMiddleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withMiddleware(function (Middleware $middleware): void {
        // ... middleware lain tetap ada

        $middleware->alias([
            'sso' => SsoMiddleware::class,
        ]);
    })
    ->create();
```

---

### Langkah 6 — Proteksi routes di `routes/web.php`

```php
// Route publik (tidak perlu login)
Route::inertia('/', 'welcome')->name('home');

// Route yang memerlukan SSO login
Route::middleware('sso')->group(function () {
    Route::inertia('/dashboard', 'Dashboard')->name('dashboard');
    // tambahkan route lain di sini
});
```

---

### Langkah 7 — Update `HandleInertiaRequests.php`

Ganti `$request->user()` dengan data dari session SSO:

```php
public function share(Request $request): array
{
    return [
        ...parent::share($request),
        'name' => config('app.name'),
        'auth' => [
            'user' => $request->session()->get('sso_user'),
        ],
    ];
}
```

Data `sso_user` berisi:

```php
[
    'id'     => 1,
    'uuid'   => 'xxxxxxxx-...',
    'name'   => 'Admin',
    'email'  => 'admin@gmp.local',
    'role'   => 'super_admin',
    'status' => 'active',
]
```

---

### Langkah 8 — Hapus sistem login lama

- Hapus route `/login` dan `/logout` lama
- Hapus `LoginController` / `AuthController` lama
- Hapus middleware `auth` bawaan Laravel dari routes (ganti dengan `sso`)
- Hapus session `Auth::attempt` / `Auth::login`

---

### Langkah 9 — Update `dev` script di `composer.json`

Tambahkan `--port` agar tidak bentrok dengan app lain:

```json
"dev": [
    "Composer\\Config::disableProcessTimeout",
    "npx concurrently -c \"#93c5fd,#c4b5fd,#fdba74\" \"php artisan serve --port=XXXX\" \"php artisan queue:listen --tries=1\" \"npm run dev\" --names='server,queue,vite'"
]
```

> Ganti `XXXX` dengan port yang belum dipakai. Lihat daftar port di bawah.

---

## Skenario B — App Laravel Blade (tanpa Inertia)

Langkah 1–8 **sama persis** dengan Skenario A.

Perbedaan hanya cara mengakses data user:

**Di Controller:**
```php
$user = session('sso_user');
// $user['name'], $user['email'], $user['role'], dst.
```

**Di Blade:**
```blade
{{ session('sso_user')['name'] }}
{{ session('sso_user')['role'] }}
```

**Untuk cek di middleware/logic:**
```php
if (!session()->has('sso_user')) {
    // belum login (seharusnya tidak terjadi jika route sudah pakai middleware sso)
}
```

---

## Skenario C — App Non-Laravel

Hubungi tim platform — dibutuhkan implementasi khusus karena perlu:
- HTTP client untuk validasi token ke `GET /api/user`
- Manajemen session sendiri

---

## Daftar Port yang Digunakan

| App | Port |
|-----|------|
| `apps/auth` | 8000 |
| `apps/finance` | 8002 |
| *(app baru berikutnya)* | 8003, 8004, dst. |

---

## Checklist Cepat

```
□ Taruh app di apps/
□ composer.json → tambah gmp/laravel-core + repositories + minimum-stability: dev
□ composer update gmp/laravel-core
□ Buat config/sso.php
□ Tambah AUTH_APP_URL di .env
□ bootstrap/app.php → alias 'sso' => SsoMiddleware::class
□ routes/web.php → Route::middleware('sso')->group(...)
□ HandleInertiaRequests.php → pakai session('sso_user')
□ Hapus login lama (route, controller, middleware auth)
□ Update port di composer.json dev script
```

---

---

## Production — Subdomain Setup

Contoh: `sso.persadalab.com`, `finance.persadalab.com`, `ecustomer.persadalab.com`

### `.env` per App

**`apps/auth` → `sso.persadalab.com`**
```env
APP_URL=https://sso.persadalab.com
SESSION_DOMAIN=.persadalab.com
SANCTUM_STATEFUL_DOMAINS=sso.persadalab.com,finance.persadalab.com,ecustomer.persadalab.com
```

**`apps/finance` → `finance.persadalab.com`**
```env
APP_URL=https://finance.persadalab.com
AUTH_APP_URL=https://sso.persadalab.com
SESSION_DOMAIN=.persadalab.com
```

**`apps/ecustomer` → `ecustomer.persadalab.com`**
```env
APP_URL=https://ecustomer.persadalab.com
AUTH_APP_URL=https://sso.persadalab.com
SESSION_DOMAIN=.persadalab.com
```

> Pola yang sama berlaku untuk semua app baru — cukup ganti `APP_URL` dan pastikan `AUTH_APP_URL` selalu menunjuk ke `sso.persadalab.com`.

---

### Setup Sanctum di `apps/auth`

Publish config Sanctum (hanya sekali):

```bash
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
```

Pastikan `config/sanctum.php` menggunakan env variable:

```php
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost')),
```

---

### Alur di Production

```
User buka finance.persadalab.com/dashboard
    └─ tidak ada session
        └─ redirect → sso.persadalab.com/login?redirect_url=https://finance.persadalab.com/dashboard
            └─ login berhasil
                └─ redirect → finance.persadalab.com/dashboard?sso_token=xxx
                    └─ SsoMiddleware: call GET https://sso.persadalab.com/api/user
                        └─ token valid → simpan ke session → masuk ✓
```

---

### Checklist Shared Hosting

| Item | Keterangan |
|------|-----------|
| **PHP ≥ 8.2** | Pastikan setiap subdomain bisa set PHP version sendiri di cPanel |
| **`allow_url_fopen = On`** | Wajib — dipakai `SsoClient` untuk HTTP request ke auth server |
| **HTTPS** | Wajib di production. `APP_URL` harus `https://` |
| **Session driver** | Gunakan `database` atau `redis`, bukan `file` |
| **`.htaccess`** | Pastikan `public/.htaccess` ada dan `AllowOverride All` aktif |
| **Storage symlink** | Jalankan `php artisan storage:link` setelah deploy |
| **`APP_ENV=production`** | Wajib di semua app |
| **`APP_DEBUG=false`** | Wajib di semua app saat production |

---

### Struktur Folder di Shared Hosting (cPanel)

```
public_html/                        ← tidak dipakai
sso.persadalab.com/
    ├── public/                     ← document root subdomain ini
    └── ... (seluruh apps/auth)
finance.persadalab.com/
    ├── public/                     ← document root subdomain ini
    └── ... (seluruh apps/finance)
ecustomer.persadalab.com/
    ├── public/                     ← document root subdomain ini
    └── ... (seluruh apps/ecustomer)
```

> Di cPanel → **Subdomains** → set **Document Root** ke `sso.persadalab.com/public` (bukan root app).

---

## File Kunci di `packages/laravel-core`

| File | Fungsi |
|------|--------|
| `src/Middleware/SsoMiddleware.php` | Cek session, redirect ke auth server, handle callback token |
| `src/Services/SsoClient.php` | HTTP request ke `GET /api/user` untuk validasi token |

## Endpoint SSO di `apps/auth`

| Method | URL | Fungsi |
|--------|-----|--------|
| `GET` | `/login?redirect_url=...` | Halaman login (simpan redirect_url ke session) |
| `POST` | `/login` | Proses login, issue token, redirect balik |
| `GET` | `/api/user` | Validasi token, return data user (auth:sanctum) |
| `DELETE` | `/api/token` | Revoke token / logout remote (auth:sanctum) |
