=== 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 ` **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.