passbolt/passbolt_api · error · ForbiddenException
The authentication token is missing.
Error message
The authentication token is missing.
What it means
Thrown by TransfersUpdateService::assertOperationIsAllowed when the loaded transfer has no associated authentication token entity. A mobile transfer must carry an active TYPE_MOBILE_TRANSFER authentication token to authorize page uploads.
Solutions
- Restart the mobile transfer flow: create a new authentication token (mobile-transfer type) and a new transfer
- Check the authentication_tokens table for an active token linked to the transfer's user
- Do not reuse transfers across sessions; tokens are single-flow
Defensive patterns
Strategy: validation
Validate before calling
const token = transfer.authenticationToken;
if (!token) {
// token missing: restart transfer setup to obtain one
await startMobileTransferFlow();
} Type guard
function hasAuthToken(t) {
return t != null && typeof t === 'object' && 'id' in t.authenticationToken && t.authenticationToken != null;
} Try / catch
try {
await api.updateTransfer(transferId, payload);
} catch (e) {
if (e.code === 403 && e.message.includes('authentication token is missing')) {
await restartTransferSetup();
}
} Prevention
- Always run the create-transfer step which provisions the token
- Persist the token with the transfer and verify presence before each update
- Check for token cleanup jobs that may delete it mid-flow
When it happens
Trigger: Updating a transfer whose authentication_token relation is unset — typically because the token was deleted/consumed, the transfer was created outside the mobile-transfer flow, or the token association failed to load.
Common situations: Token deleted by a cleanup task or by completing another transfer; reusing a transfer after its token was deactivated; client skipping the transfer-create step that generates the token.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- The authentication token is expired.
- The authentication token is not active.
- The authentication token is not valid for this user.
- The authentication token type is invalid.
- This operation is not allowed for this user.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/0f6b2c78edf28546.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltCe/Mobile/src/Service/Transfers/TransfersUpdateService.php:164
}
/**
* Check if operation is allowed
*
* @param \Passbolt\Mobile\Model\Entity\Transfer $transfer entity
* @param \App\Utility\UserAccessControl $uac user access control object
* @throws \Cake\Http\Exception\ForbiddenException if operation is not allowed for example:
* - Transfer or AuthToken is for another user
* - Authentication token is expired
* @return void
*/
private function assertOperationIsAllowed(Transfer $transfer, UserAccessControl $uac): void
{
if ($transfer->user_id !== $uac->getId()) {
throw new ForbiddenException(__('This operation is not allowed for this user.'));
}
if (!isset($transfer->authentication_token)) {
throw new ForbiddenException(__('The authentication token is missing.'));
}
if ($transfer->authentication_token->user_id !== $uac->getId()) {
throw new ForbiddenException(__('The authentication token is not valid for this user.'));
}
if ($transfer->authentication_token->type !== AuthenticationToken::TYPE_MOBILE_TRANSFER) {
throw new ForbiddenException(__('The authentication token type is invalid.'));
}
if ($transfer->authentication_token->active !== true) {
throw new ForbiddenException(__('The authentication token is not active.'));
}
if ($transfer->authentication_token->isExpired()) {
throw new ForbiddenException(__('The authentication token is expired.'));
}
}
/**
* Return an updated transfer entity.
*View on GitHub (pinned to 31c1bbc10f)