Authentication¶
The Knosc API uses cookie-based JWT (JSON Web Token) authentication. All endpoints require a valid session before returning data.
Base URLs¶
| Environment | Base URL |
|---|---|
| Production | https://{company}.knosc.com/api |
| Test | https://{company}.knosc.io/api |
Replace {company} with your organisation's subdomain identifier.
Overview¶
| Property | Value |
|---|---|
| Mechanism | HTTP-only cookies |
| Token type | JWT (JSON Web Token) |
| Access token cookie | access_token_cookie |
| Refresh token cookie | refresh_token_cookie |
| CSRF protection | Enabled for state-modifying requests |
| CSRF header | X-XSRF-TOKEN |
Obtaining a Session¶
POST /api/authenticate
Content-Type: application/json
{
"username": "jane.doe@acme.com",
"password": "your-password"
}
On success, the server sets access_token_cookie and refresh_token_cookie as HttpOnly cookies, and csrf_access_token / csrf_refresh_token as readable cookies for CSRF protection.
HTTP/1.1 200 OK
Set-Cookie: access_token_cookie=<jwt>; HttpOnly; SameSite=Lax
Set-Cookie: csrf_access_token=<csrf-token>; SameSite=Lax
Full details: Login & Logout
Two-Factor Authentication¶
When 2FA is enabled on an account, login returns {"requires_2fa": true} instead of a full session. Submit the TOTP code to /api/verify-2fa to complete the flow.
Full details: Two-Factor Authentication
Making Authenticated Requests¶
Because the access token is stored in an HttpOnly cookie, your HTTP client must:
- Send cookies automatically with every request.
- Include the CSRF token header on
POST,PUT,PATCH, andDELETErequests.
POST /api/purchase-order HTTP/1.1
Host: acme.knosc.com
Cookie: access_token_cookie=<jwt>
X-XSRF-TOKEN: <value-of-csrf_access_token-cookie>
Content-Type: application/json
{ ... }
CSRF Protection¶
State-modifying requests (POST, PUT, PATCH, DELETE) must include the X-XSRF-TOKEN header. Read its value from the csrf_access_token cookie set during login.
import requests
session = requests.Session()
# Authenticate
session.post("https://acme.knosc.com/api/authenticate", json={
"username": "jane.doe@acme.com",
"password": "your-password"
})
csrf_token = session.cookies.get("csrf_access_token")
# Use for state-modifying requests:
session.post(
"https://acme.knosc.com/api/purchase-order",
headers={"X-XSRF-TOKEN": csrf_token},
json={ ... }
)
Token Expiry and Refresh¶
Access tokens expire after a set period. Use the refresh token to obtain a new one without re-authenticating.
Full details: Token Refresh
Token Invalidation¶
Tokens are automatically invalidated when the associated user account is modified (password change, role change, suspension). The token carries a last_modified_at claim compared on every request.
Privilege Model¶
Authentication alone does not grant access to all endpoints. Each endpoint requires a specific privilege and access level assigned to the authenticated user's role.
| Privilege Type | Access Level | Grants |
|---|---|---|
Procurement |
View |
Read purchase orders, details, item data |
Procurement |
Edit |
Create, update, delete purchase orders and details |
Demand |
View |
Read sales orders |
Demand |
Edit |
Create, update, delete sales orders |
Manufacturing |
View |
Read manufacturing orders |
Inventory |
View |
Read inventory |
Inventory Planning |
View |
Read planning data |
Forecast |
View |
Read forecasts |
Users |
View |
List users |
Users |
Edit |
Create, update, delete users |
| (and more) |
Requests without the required privilege return:
HTTP/1.1 403 Forbidden
{
"Message": "Not Privileged for this action",
"Code": "User.NotPrivileged"
}
Error Reference¶
| Scenario | HTTP Status |
|---|---|
| Missing or invalid token | 401 |
| Expired token | 401 |
| Insufficient privilege | 403 |
| Missing CSRF token | 422 |