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

  1. Restart the mobile transfer flow: create a new authentication token (mobile-transfer type) and a new transfer
  2. Check the authentication_tokens table for an active token linked to the transfer's user
  3. 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

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

Related errors


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)