# Square OAuth Broker (Validakey / RoundPeg)

Standalone HTTPS token broker for RoundPeg Square OAuth. Holds the Square **Application Secret** so it never ships inside the sold WordPress plugin. Sellers authorize RoundPeg without creating Square developer accounts.

**Intended public URL:** `https://oab.validakey.com/`

## What it does

| Method | Path | Purpose |
|--------|------|---------|
| `GET` | `/` | Health / config summary (no secrets) |
| `GET` | `/square/start` | Begin OAuth (`return_url`, `state`) → redirect to Square |
| `GET` | `/square/callback` | Square redirect URI → `ObtainToken` → redirect to plugin with one-time `square_oauth_claim` |
| `POST` | `/square/redeem` | Exchange claim → seller tokens (JSON) |
| `POST` | `/square/refresh` | Refresh seller access token |
| `POST` | `/square/revoke` | Revoke seller token(s) |

No product UI. Connect / Disconnect live in RoundPeg Settings. This service only shows bare HTML on invalid requests or auth denial edge cases.

### Default scopes

`ITEMS_READ MERCHANT_PROFILE_READ CUSTOMERS_READ LOYALTY_READ`

(Catalog, Locations/Merchant Profile, Customers incl. groups/segments/custom attributes, Loyalty.)

## Install on this server

Code currently lives at:

`/home/art/oab.validakey.com`

(Creating `/var/www/oab.validakey.com` needs root.)

```bash
# 1) Place the app
sudo mkdir -p /var/www/oab.validakey.com
sudo rsync -a /home/art/oab.validakey.com/ /var/www/oab.validakey.com/
sudo chown -R www-data:www-data /var/www/oab.validakey.com
sudo chmod -R g+w /var/www/oab.validakey.com/storage

# 2) Configure secrets
cd /var/www/oab.validakey.com
sudo -u www-data cp .env.example .env
sudo -u www-data nano .env   # fill Square Application ID/Secret

# 3) Autoload
cd /var/www/oab.validakey.com && sudo -u www-data composer install --no-dev

# 4) Apache vhost
sudo cp deploy/oab.validakey.com.conf /etc/apache2/sites-available/
sudo a2ensite oab.validakey.com.conf
sudo a2enmod rewrite
sudo systemctl reload apache2

# 5) DNS A/AAAA for oab.validakey.com → this host, then:
sudo certbot --apache -d oab.validakey.com
```

Confirm DocumentRoot is `.../public` (not the repo root).

## Square Developer Console

1. Open your RoundPeg Square application.
2. **OAuth → Redirect URL** (exact):

   `https://oab.validakey.com/square/callback`

3. Use Sandbox credentials while `SQUARE_ENVIRONMENT=sandbox`, Production when live.
4. Production authorize uses `session=false` (enforced by this broker).

## Plugin handshake (contract)

### Start

Browser (from WP admin):

```
GET https://oab.validakey.com/square/start
  ?return_url=https%3A%2F%2Fshop.example%2Fwp-admin%2Foptions-general.php%3Fpage%3Droundpeg%26roundpeg_tab%3Dsettings
  &state=<random-16+-chars>
```

`return_url` must be `https` and, when `ALLOWED_RETURN_HOSTS=*`, must contain `/wp-admin`.

### Callback → Settings

Broker redirects to `return_url` with:

- success: `square_oauth=success&square_oauth_claim=<id>&state=<client-state>`
- error: `square_oauth=error&square_oauth_error=...&state=...`

### Redeem (server-side from WordPress)

```http
POST /square/redeem
Content-Type: application/json
X-Broker-Key: <BROKER_API_KEY if set>

{"claim":"<id>","state":"<client-state>"}
```

Response includes `access_token`, `refresh_token`, `expires_at`, `merchant_id`, `scopes`. Claim is one-time and short-lived.

### Refresh / revoke

```http
POST /square/refresh
{"refresh_token":"..."}

POST /square/revoke
{"access_token":"..."} 
# or {"merchant_id":"..."}
```

## Local smoke test (before DNS)

```bash
cd /home/art/oab.validakey.com
cp .env.example .env
# edit .env with sandbox credentials; set BROKER_BASE_URL=http://127.0.0.1:8088
composer install
php -S 127.0.0.1:8088 -t public
curl -s http://127.0.0.1:8088/ | jq .
```

## Security notes

- Never commit `.env`.
- `storage/state` and `storage/claims` hold short-lived secrets; keep directory permissions tight (`www-data`, not world-readable).
- Prefer setting `BROKER_API_KEY` and sending `X-Broker-Key` from the plugin for redeem/refresh/revoke.
- Prefer locking `ALLOWED_RETURN_HOSTS` to known customer hostnames when you can; `*` is for a general sold plugin.
