BookStackApp/BookStack · error · ApiAuthException
errors.api_cookie_auth_only_get
Error message
errors.api_cookie_auth_only_get
What it means
This BookStack API-auth middleware throws ApiAuthException (HTTP 403) when a request is authenticated via the session cookie rather than an API token and the HTTP method is not GET. Cookie-based API access is deliberately limited to read-only GET requests for security (CSRF risk); any POST/PUT/PATCH/DELETE from a cookie session is rejected.
Source
Thrown at app/Http/Middleware/ApiAuthenticate.php:43
/**
* Ensure the current user can access authenticated API routes, either via existing session
* authentication or via API Token authentication.
*
* @throws ApiAuthException
*/
protected function ensureAuthorizedBySessionOrToken(Request $request): void
{
// Use the active user session already exists.
// This is to make it easy to explore API endpoints via the UI.
if (session()->isStarted()) {
// Ensure the user has API access permission
if (!$this->sessionUserHasApiAccess()) {
throw new ApiAuthException(trans('errors.api_user_no_api_permission'), 403);
}
// Only allow GET requests for cookie-based API usage
if ($request->method() !== 'GET') {
throw new ApiAuthException(trans('errors.api_cookie_auth_only_get'), 403);
}
return;
}
// Set our api guard to be the default for this request lifecycle.
auth()->shouldUse('api');
// Validate the token and its users API access
auth()->authenticate();
}
/**
* Check if the active session user has API access.
*/
protected function sessionUserHasApiAccess(): bool
{
$hasApiPermission = user()->can(Permission::AccessApi);View on GitHub (pinned to 18f8469a1c)
Solutions
- Obtain an API token (User Profile > API Tokens) and send header 'Authorization: Token <id>:<secret>' on the request
- Change the request to a GET if a read was intended (check HTTP method, e.g. fetch defaults)
- If calling from your own frontend, route mutations through a server-side proxy that authenticates with a token
- Verify no middleware/proxy strips the Authorization header, causing fallback to cookie auth
Example fix
// before
fetch('/api/books', { method: 'POST', credentials: 'include', body })
// after
fetch('/api/books', { method: 'POST', headers: { 'Authorization': 'Token ' + id + ':' + secret, 'Content-Type': 'application/json' }, body }) Defensive patterns
Strategy: try-catch
Validate before calling
const isCookieAuth = !headers.get('Authorization')?.startsWith('Token ');
if (isCookieAuth && method !== 'GET') {
throw new Error('Cookie-based API auth only allows GET requests; use a token for mutations.');
} Type guard
function usesTokenAuth(headers) {
return /^Token\s+[\w-]+:[\w-]+$/.test(headers.get('Authorization') ?? '');
} Try / catch
try {
const res = await fetch(url, options);
if (res.status === 403) {
const body = await res.json();
if (body?.message?.includes('api_cookie_auth_only_get')) {
// switch to token auth or change method to GET
}
}
} catch (e) { /* network error handling */ } Prevention
- Always use API tokens (Authorization: Token id:secret) for non-GET requests
- Never rely on session cookies for programmatic API mutations
- Audit client code for methods other than GET when credentials: 'include' is used
- Check proxies/SDKs don't strip the Authorization header
When it happens
Trigger: A logged-in browser session (session cookie) calls any non-GET API endpoint, e.g. a fetch() with method POST/PUT/DELETE while relying on the session cookie instead of an API token with header Authorization: Token <id>:<secret>.
Common situations: Frontend scripts reusing the logged-in session cookie to mutate data; API clients that never obtained a token; proxies/SDKs stripping the Authorization header so the request falls back to cookie auth; testing mutations in a browser console while logged in.
Related errors
- Unauthorized
- errors.email_confirmation_awaiting
- errors.api_no_authorization_found
- errors.api_bad_authorization_format
- errors.api_user_token_not_found
AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02).
Data as JSON: /api/errors/53b2378b981bc172.
Report an issue: GitHub.