# cPanel / Shared Hosting Server-Level Setup

This version is designed for normal cPanel hosting where you usually have Apache + PHP access but no Cloudflare, no root server modules, no Composer, and no database driver.

## Quick deployment

Upload the full folder here:

```text
public_html/fingerprint_guard/
```

Then open:

```text
https://yourdomain.com/fingerprint_guard/public/example-page.php
https://yourdomain.com/fingerprint_guard/public/signup.php
https://yourdomain.com/fingerprint_guard/public/login.php
https://yourdomain.com/fingerprint_guard/public/my-browser-security.php
```

## Signup and login

This package now includes a working file-based demo auth system:

```text
public/signup.php
public/login.php
public/logout.php
public/dashboard.php
lib/AuthStore.php
storage/users/
```

Signup stores users in `storage/users/*.json` using PHP `password_hash()`. The browser/account link uses:

```php
$_SESSION['user_id'] = 'user:' . $username;
```

After signup/login, the code calls:

```php
$guard = new FingerprintGuard();
$guard->linkAccount((string)$_SESSION['user_id']);
```

That is how the same logged-in user gets matched to the same browser token on future visits.

For your real application, replace the demo auth with your own signup/login and keep the same session line after successful login:

```php
session_start();
$_SESSION['user_id'] = (string)$realUserId;
```

## Writable folders

Make sure PHP can write to:

```text
storage/users
storage/browsers
storage/observations
storage/accounts
storage/events
storage/index
storage/index/ip_accounts
storage/index/stable_accounts
storage/index/browser_accounts
```

On many cPanel hosts `0755` works. If PHP cannot write, use `0775`. Avoid `0777` unless your host requires it and you understand the risk.

The included `storage/.htaccess` and `storage/users/.htaccess` block direct browser access to stored JSON files on Apache/cPanel.

## Production secret

Generate a secret:

```bash
php -r "echo bin2hex(random_bytes(32)), PHP_EOL;"
```

Put it in `lib/FingerprintGuard.php`:

```php
private const APP_SECRET = 'YOUR_64_HEX_SECRET_HERE';
```

If you change the secret later, old browser-token cookies will become invalid and users will receive new browser tokens.

## What this package can collect on cPanel

From PHP/Apache it stores and matches:

- IP seen by PHP: `REMOTE_ADDR`
- forwarded IP headers if your host/proxy provides them: `X-Forwarded-For`, `X-Real-IP`
- HTTP method, URI, host, protocol, HTTPS status, content type, content length
- all request headers available to PHP, with `Cookie` and `Authorization` redacted
- User-Agent header
- Accept / Accept-Language / Accept-Encoding
- Sec-CH-UA / Sec-CH-UA-Mobile / Sec-CH-UA-Platform where the browser sends them
- Sec-Fetch-* headers where the browser sends them
- DNT / Upgrade-Insecure-Requests
- request + client mismatch checks
- IP changes under the same browser token
- same browser token across multiple accounts
- same stable fingerprint across multiple accounts
- same server IP across multiple accounts

## What plain cPanel PHP cannot see

Normal PHP on shared hosting cannot directly see TLS JA3/JA4, real TCP behavior, HTTP/2 frame fingerprints, or raw header order. Those require control of the TLS/web-server layer. This package still adds the maximum practical server-side checks available from PHP itself.

## Better folder placement for production

Best option if your cPanel allows files outside `public_html`:

```text
/home/USER/fingerprint_guard_private/
  lib/
  storage/

/home/USER/public_html/fingerprint_guard/
  public files only
```

Then adjust public PHP files from:

```php
require_once __DIR__ . '/../lib/FingerprintGuard.php';
require_once __DIR__ . '/../lib/AuthStore.php';
```

to the real private path, for example:

```php
require_once '/home/USER/fingerprint_guard_private/lib/FingerprintGuard.php';
require_once '/home/USER/fingerprint_guard_private/lib/AuthStore.php';
```

Simplest option for testing:

```text
public_html/fingerprint_guard/
  lib/
  storage/
  public/
```

The included `.htaccess` files block direct access to `storage`, but private placement is still cleaner.

## Add the widget to your site

```html
<script src="/fingerprint_guard/public/fp-widget.js"></script>
<script>
window.FingerprintGuard.collect({
  endpoint: '/fingerprint_guard/public/collect.php',
  nonceEndpoint: '/fingerprint_guard/public/nonce.php',
  mode: 'strict'
});
</script>
```

Add that on signup, login, dashboard, checkout, posting, messaging, password reset, and any page where automation/risk matters.

## API endpoints

- `public/signup.php` — creates a demo local user and links browser.
- `public/login.php` — logs in demo user and links browser.
- `public/logout.php` — logs out demo user.
- `public/dashboard.php` — simple logged-in test page.
- `public/nonce.php` — creates a one-time collection nonce in the PHP session.
- `public/collect.php` — receives client fingerprint + stores raw client and server context.
- `public/risk-report.php` — latest risk for current browser token.
- `public/account-report.php` — current logged-in account browser report.
- `public/account-report.php?raw=1` — includes latest raw payload for the current logged-in account.
- `public/my-browser-security.php` — HTML page users can view.
- `public/my-browser-security-data.php` — JSON used by the user-facing page.

## Matching logic

The system matches these layers together:

```text
browser token cookie
+ stable browser fingerprint
+ volatile browser fingerprint
+ full raw JS payload hash
+ raw server request/header fingerprint
+ account id from PHP session
+ hashed IP index
+ stable fingerprint/account index
+ browser token/account index
```

That lets the backend detect:

- same token but changed browser/device fingerprint
- same account but new token/browser
- same token used by multiple accounts
- same fingerprint used by multiple accounts
- same server IP used by many accounts
- JS User-Agent/header User-Agent mismatch
- JS language/header language mismatch
- Sec-CH-UA mobile mismatch
- direct non-browser clients such as curl, wget, Python requests, Go HTTP clients
- missing/replayed collection nonce
