Download the PHP package heinhtet/api-authorizer without Composer
On this page you can find all versions of the php package heinhtet/api-authorizer. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download heinhtet/api-authorizer
More information about heinhtet/api-authorizer
Files in heinhtet/api-authorizer
Package api-authorizer
Short Description Protect Laravel APIs with HMAC-SHA256 request signing headers (X-POWERED-BY, X-TIMESTAMP, X-SIGNATURE) - authenticity, tamper-proofing and replay-attack prevention.
License MIT
Homepage https://github.com/heinhtet/api-authorizer
Informations about the package api-authorizer
Laravel API Authorizer
Protect public and internal Laravel APIs with HMAC-SHA256 request signing. Every request must carry a
signed set of headers (X-POWERED-BY, X-TIMESTAMP, X-SIGNATURE) that prove the caller is authentic,
that the request was not tampered with in transit, and that it is not a replay of a previously captured
request.
This package is the reusable, hardened version of an in-app middleware: it fixes the timestamp check, sorts query parameters into the documented canonical order, supports multiple clients with independent secrets, never logs secrets or signatures, and ships with tests and a client-side signer.
- Authenticity — only holders of a client secret can produce a valid signature.
- Integrity — method, path, query string and body are all covered by the HMAC.
- Replay protection — requests outside the configured time window are rejected.
- Multi-tenant — every
X-POWERED-BYclient maps to its own secret (config or your own repository). - Zero surprises — timing-safe comparison, canonical query sorting, JSON error envelope, request tracing.
Requirements
- PHP 8.3+
- Laravel 10, 11, 12 or 13
Installation
Publish the configuration file:
Add the credentials to your .env:
Secrets are per client. Never commit them, never log them, never ship them inside a browser bundle.
Usage
The middleware is registered under the api.authorizer alias. Apply it to the APIs you want to protect.
Or globally for every API route in bootstrap/app.php:
Or on a single route:
Accessing the verified client
Once a request passes verification the resolved client is attached to the request attributes:
Required headers
| Header | Description | Notes |
|---|---|---|
X-POWERED-BY |
Unique identifier of the frontend client or app | Maps to a secret on the server |
X-TIMESTAMP |
Current Unix timestamp in seconds (UTC) | Used for replay attack prevention |
X-SIGNATURE |
HMAC-SHA256 of the canonical request | Ensures integrity and authenticity |
X-REQUEST-ID |
Optional correlation id for tracing | Echoed back in the response, useful for logs |
The header names are configurable (see Configuration).
Canonical request format
The signature is computed over this exact string:
| Component | Rule |
|---|---|
METHOD |
HTTP method, uppercase (GET, POST, PUT, ...) |
PATH |
API path only, e.g. /api/v1/orders — no scheme, host or query string |
SORTED_QUERY |
Query parameters sorted alphabetically by key (then value), joined with &. Empty when none. |
TIMESTAMP |
The same value sent in X-TIMESTAMP |
BODY |
Raw JSON request body for POST/PUT/PATCH/DELETE. Always empty for GET/HEAD. |
Example GET with query parameters:
Example POST with a JSON body:
Both client and server must build this string identically. Query parameters may be sent in any order —
the package sorts them before signing and before verifying, so status=paid&page=1 and
page=1&status=paid produce the same signature.
Signature generation
- Algorithm: HMAC-SHA256
- Key: the client secret assigned by the backend (
API_AUTHORIZER_SECRET_*) - Input: the canonical request string
- Output: lowercase hex (default) or base64 — configure
api-authorizer.encoding
Worked example, using the secret super-secret-key:
The body is signed byte-for-byte. Send exactly the JSON you signed — the server hashes the raw request body, not a re-serialized copy.
Signing from PHP (server-to-server)
Use the bundled signer, which builds the headers for you:
Or sign an existing request instance:
Signing without this package (any language)
The algorithm is plain HMAC-SHA256 over the canonical string, so any HTTP client can implement it:
curl example
X-TIMESTAMPmust be within the allowed window of the server clock. Generate the timestamp and the signature in the same step — a hardcoded pair only works while it is fresh.
Timestamp validation
The client sends a UTC timestamp in seconds. The backend accepts a configurable window
(tolerance, default 300 seconds / ±5 minutes) to absorb clock skew and rejects anything outside
of it as Request expired. — this is what makes replaying a captured request useless.
Error responses
Rejected requests return HTTP 401 with a JSON envelope:
errors.code |
status_code (default) |
Message |
|---|---|---|
missing_header |
1001 | Missing required headers: X-POWERED-BY, ... |
invalid_timestamp |
1002 | Invalid timestamp. |
expired_timestamp |
1003 | Request expired. |
unknown_client |
1004 | Invalid client. |
invalid_signature |
1005 | Invalid signature. |
When an X-REQUEST-ID header is present it is echoed back on both successful and rejected responses so
you can correlate client and server logs.
Configuration
The error_codes map lets you align status_code values with your application's own error catalog.
Storing clients in the database
Implement ClientRepositoryInterface and bind it in a service provider to resolve secrets from the
database, a cache or a secrets manager instead of the config file:
Development bypass
For local development you can allow a request to skip verification with a shared bypass key:
Keep the bypass disabled in production and store the key in .env only.
Security best practices
- Issue a unique secret per client and rotate it if a device or build is compromised.
- Store secrets in secure device storage: iOS Keychain, Android Keystore, OS credential store.
- Never embed secrets in browser-side code. Prefer a backend-for-frontend (BFF) that signs on behalf of the browser.
- Always run signed APIs over HTTPS.
- Never log secrets or signatures; this package only logs non-sensitive metadata (and only when logging is enabled).
- Keep the timestamp tolerance small enough to limit replay windows but large enough for clock skew.
Testing
To test your own signed routes, let the package sign the request for you:
Contributing
Please read CONTRIBUTING.md before opening a pull request. Security issues are handled privately as described in SECURITY.md, not in the public issue tracker. Release notes live in CHANGELOG.md.
License
API Authorizer is open-sourced software licensed under the MIT license.
All versions of api-authorizer with dependencies
illuminate/http Version ^10.0|^11.0|^12.0|^13.0
illuminate/support Version ^10.0|^11.0|^12.0|^13.0