passbolt/passbolt_api · error · ForbiddenException

The authentication token type is invalid.

Error message

The authentication token type is invalid.

What it means

Type guard for mobile transfers: the transfer's authentication token type does not match the expected mobile transfer type, meaning the token presented was minted for a different purpose, so the operation is denied with 403.

Solutions

  1. Create the token with AuthenticationToken::TYPE_MOBILE_TRANSFER via the mobile transfer setup endpoint
  2. Verify the token's type column in authentication_tokens before use
  3. Start the documented mobile transfer flow instead of hand-crafting tokens

Example fix

// before
$token = AuthenticationTokenFactory::make()->type(AuthenticationToken::TYPE_RECOVER)->...;
// after
$token = AuthenticationTokenFactory::make()->type(AuthenticationToken::TYPE_MOBILE_TRANSFER)->...;
Defensive patterns

Strategy: validation

Validate before calling

const token = transfer.authenticationToken;
if (token && token.type !== 'mobile-transfer') {
  throw new Error('Wrong token type: must be mobile-transfer');
}

Type guard

function isMobileTransferToken(t) {
  return t?.authenticationToken?.type === 'mobile-transfer';
}

Try / catch

try {
  await api.updateTransfer(transferId, payload);
} catch (e) {
  if (e.code === 403 && e.message.includes('token type is invalid')) {
    // recreate the token with the mobile-transfer type via setup endpoint
  }
}

Prevention

When it happens

Trigger: Updating a transfer while the linked token is of another type (e.g. a recover or register token) — usually from a custom script creating the token with the wrong type constant, or fixture reuse across flows.

Common situations: Reusing an AuthenticationToken created for account recovery in the mobile transfer flow; API scripting mistakes passing a token from another feature; older tokens created before the mobile-transfer type existed.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/f3d0c681f58f5fe8. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/Mobile/src/Service/Transfers/TransfersUpdateService.php:170

     * @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.
     *
     * @param \Passbolt\Mobile\Model\Entity\Transfer $transfer entity
     * @param array $data data
     * @return \Passbolt\Mobile\Model\Entity\Transfer
     */
    private function patchTransferEntity(Transfer $transfer, array $data): Transfer
    {

View on GitHub (pinned to 31c1bbc10f)