=== HeadlessKey – JWT Auth ===
Contributors: hidayatsafewp
Tags: jwt, authentication, rest api, security, headless
Requires at least: 6.0
Requires PHP: 8.0
Tested up to: 6.9
Stable tag: 1.0.0
License: GPLv2
License URI: https://www.gnu.org/licenses/gpl-2.0.html

A complete authentication solution for Headless WordPress applications using JWT, supporting Registration, SSO, RBAC, and advanced Security features.

== Description ==

**HeadlessKey – JWT Auth** extends the REST API to provide a robust and secure authentication system using JSON Web Tokens (JWT). Designed for Headless WordPress, it enables seamless user authentication, registration, and session management via standard REST endpoints.

### Key Features
*   **Standard JWT Authentication**: Secure user authentication using industry-standard RFC 7519 tokens.
*   **Multiple Algorithms**: Support for `HS256`, `RS256`, and `ES256` signing algorithms.
*   **Comprehensive Endpoints**: Ready-to-use endpoints for Login, Register, Token Refresh, and Password Management.
*   **Single Sign-On (SSO)**: Connect multiple sites with a secure, headers-based SSO exchange mechanism.
*   **Role-Based Access Control (RBAC)**: Configure public or authenticated access for every endpoint.
*   **Brute Force Protection**: Protects against attacks by locking users/IPs after failed attempts.
*   **Activity Logs**: Detailed audit trail of all authentication events, including IP and device data.
*   **Security Webhooks**: Real-time JSON events sent to your external services for monitoring key actions.
*   **Device Limits**: Restrict the number of active devices/sessions per user.
*   **Developer Friendly**: Extensive hooks and filters for deep customization.

== Configuration ==

### Secret Key
The plugin uses a secret key to sign tokens. By default, a secure random key is generated. For better security and consistency across environments, define your key in `wp-config.php`:

`define('headlesskey_SECRET_KEY', 'your-long-random-secure-string');`

You can generate a strong salt here: [WordPress Salt Generator](https://api.wordpress.org/secret-key/1.1/salt/)

### CORS Support
Cross-Origin Resource Sharing (CORS) is enabled by default to allow frontend applications to connect. To disable or customize it via constant:

`define('headlesskey_CORS', true); // or false to disable`

### REST API Namespace
By default, endpoints are under `wp-json/wpauthapi/v1`. You can customize this namespace:

`define('headlesskey_REST_NAMESPACE', 'my-custom-auth');`
`define('headlesskey_REST_VERSION', 'v2');`

== Endpoints ==

The plugin adds the following endpoints under the `/wp-json/headlesskey/v1` namespace:

| Endpoint | HTTP Verb | Description |
| :--- | :--- | :--- |
| `/token` | POST | **Login**: Exchange username/password for a JWT. |
| `/token/validate` | POST | **Validate**: Check if a token validity. |
| `/token/refresh` | POST | **Refresh**: Exchange a valid token for a new one (rotation). |
| `/token/revoke` | POST | **Logout**: Invalidate a specific token. |
| `/register` | POST | **Register**: Create a new user account. |
| `/login` | POST | **Profile**: Login and get full user profile data in one request. |
| `/forgot-password` | POST | **Recover**: Request a password reset via Link or OTP. |
| `/reset-password` | POST | **Reset**: Set a new password using a token or OTP. |
| `/change-password` | POST | **Update**: Change password for authenticated user. |
| `/sso/exchange` | POST | **SSO**: Exchange a remote site token for a local session. |




### 1. Login (Generate Token)

**Endpoint:** `POST /wp-json/headlesskey/v1/token`
**Description:** Authenticate a user and generate a JWT token.

**Request:**
```json
{
  "username": "admin",
  "password": "secret-password"
}
```

**Response:**
```json
{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
  "expiration": "2023-10-27T10:00:00+00:00",
  "expires_in": 3600,
  "user": {
    "ID": 1,
    "user_login": "admin",
    "user_email": "admin@example.com",
    "display_name": "Administrator",
    "roles": ["administrator"]
  },
  "refreshable": true,
  "jti": "545086b9-450f-488b-a70d-3047d14d1101"
}
```

### 2. Validate Token

**Endpoint:** `POST /wp-json/headlesskey/v1/token/validate`
**Description:** Validate if an existing token is valid.

**Request:**
```json
{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
```

**Response:**
```json
{
  "valid": true,
  "data": {
    "iss": "https://example.com",
    "iat": 1698393600,
    "exp": 1698397200,
    "data": {
      "ID": 1,
      "user_login": "admin"
    }
  }
}
```

### 3. Refresh Token

**Endpoint:** `POST /wp-json/headlesskey/v1/token/refresh`
**Description:** Rotate an expiring token for a fresh one.

**Request:**
```json
{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
```

**Response:**
```json
{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.new...",
  "expiration": "2023-10-27T11:00:00+00:00",
  "user": {
    "ID": 1,
    "user_login": "admin"
  },
  "jti": "new-uuid-v4"
}
```

### 4. Revoke Token (Logout)

**Endpoint:** `POST /wp-json/headlesskey/v1/token/revoke`
**Description:** Invalidate a token immediately.

**Request:**
```json
{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
```

**Response:**
```json
{
  "message": "Token revoked successfully."
}
```

### 5. Register User

**Endpoint:** `POST /wp-json/headlesskey/v1/register`
**Description:** Create a new user account.

**Request:**
```json
{
  "username": "johndoe",
  "email": "john@example.com",
  "password": "secure-password",
  "name": "John Doe"
}
```

**Response:**
```json
{
  "user_id": 45,
  "user": {
    "ID": 45,
    "user_login": "johndoe",
    "user_email": "john@example.com",
    "display_name": "John Doe",
    "roles": ["subscriber"]
  },
  "token_response": {
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOi...",
    "expiration": "2023-10-27T10:00:00+00:00"
  }
}
```

### 6. User Profile (Login Extended)

**Endpoint:** `POST /wp-json/headlesskey/v1/login`
**Description:** Alternative login endpoint that returns cleaner profile structure.

**Request:**
```json
{
  "username": "admin",
  "password": "secret-password"
}
```

**Response:**
```json
{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
  "expiration": "2023-10-27T10:00:00+00:00",
  "user": {
    "ID": 1,
    "user_login": "admin",
    "user_email": "admin@example.com",
    "display_name": "Administrator",
    "roles": ["administrator"]
  }
}
```

### 7. Forgot Password

**Endpoint:** `POST /wp-json/headlesskey/v1/forgot-password`
**Description:** Initiate password recovery. Note: `delivery` can be `link` or `otp`.

**Request:**
```json
{
  "login": "admin@example.com",
  "delivery": "link"
}
```

**Response:**
```json
{
  "message": "Password reset email sent."
}
```

### 8. Reset Password

**Endpoint:** `POST /wp-json/headlesskey/v1/reset-password`
**Description:** Reset password using the token sent via email or OTP.

**Request (Link method):**
```json
{
  "login": "admin@example.com",
  "password": "new-secure-password",
  "token": "generated-reset-key"
}
```

**Response:**
```json
{
  "message": "Password updated successfully."
}
```

### 9. Change Password

**Endpoint:** `POST /wp-json/headlesskey/v1/change-password`
**Description:** Change password for currently authenticated user. Requires `Authorization` header.

**Headers:**
`Authorization: Bearer <your-token>`

**Request:**
```json
{
  "current_password": "old-password",
  "new_password": "new-secure-password"
}
```

**Response:**
```json
{
  "message": "Password changed successfully. Please login again."
}
```
### 10. SSO Token Exchange

**Endpoint:** `POST /wp-json/headlesskey/v1/sso/exchange`
**Description:** Securely exchange a token from a connected remote site for a local authentication session. This powers the distributed Single Sign-On network.

**Request:**
```json
{
  "site_key": "remote-site-id",
  "token": "remote-jwt-token",
  "signature": "hmac-sha256-signature"
}
```

**Response:**
Returns a standard **Login** response (Token + User Data) if the signature is valid.

== Frequently Asked Questions ==

= How do I generate a JWT Secret? =
The plugin automatically generates a strong secret key upon activation. You can find it in the plugin settings. For better security, you can define `headlesskey_SECRET_KEY` in your `wp-config.php` file.

= Can I use this with Next.js or other frontend frameworks? =
Yes! The plugin sends correct CORS headers and returns standard JSON responses, making it compatible with any frontend framework or language that supports HTTP requests.

= Does it support Public/Private keys? =
Yes, you can configure RS256 or ES256 algorithms in the settings and provide your PEM formatted keys for asymmetric signing.

== Screenshots ==

1. General Settings - Configure Token Expiration and Security Policy.
2. Algorithms - Choose between HS256, RS256, and ES256.
3. Logs - View recent authentication activity.

== Upgrade Notice ==

= 1.0.0 =
Initial release. Secure your Headless WordPress with JWT today!

== Changelog ==

= 1.0.0 =
*   **Initial Release**: Complete authentication suite with JWT, RBAC, SSO, and Security features.
*   **Security**: Added Brute Force protection, Device Limits, and Security Webhooks.
*   **API**: Full set of endpoints for Login, Register, Password Reset, and Token Management.
