passbolt/passbolt_api · error · BadRequestException
The SSO authentication token is invalid. Token IP is…
Error message
The SSO authentication token is invalid. Token IP is missing.
What it means
A BadRequestException from assert() raised when the 'passbolt.security.userIp' check is enabled but the token's data payload lacks the IP property. getDataProperty(DATA_IP) throws AuthenticationTokenDataPropertyException, which is converted into this BadRequestException.
Solutions
- Restart the SSO flow so a fresh token is created with the IP data property under the current config
- Keep passbolt.security.userIp consistent between token creation and consumption (or restart flows after toggling it)
- Inspect the token's data JSON to confirm the ip property exists
- If the check is not required, explicitly set passbolt.security.userIp to false so the branch is skipped deterministically
Example fix
// before // token created with userIp=false, consumed with userIp=true -> missing IP // after // create and consume under the same config, or generate a fresh token: $token = $ssoTokenService->create($type, $userId, $ip, $userAgent, $settingsId);
Defensive patterns
Strategy: validation
Validate before calling
$ipEnabled = \Cake\Core\Configure::read('passbolt.security.userIp');
$hasIp = !$ipEnabled || $token->hasDataProperty(\Passbolt\Sso\Model\Entity\SsoAuthenticationToken::DATA_IP); Try / catch
try {
$service->assertAndConsume($token, $uac, $settingsId);
} catch (\Cake\Http\Exception\BadRequestException $e) {
if (str_contains($e->getMessage(), 'Token IP is missing')) {
// recreate the token under the current security config
}
} Prevention
- Keep passbolt.security.userIp consistent across token lifecycle
- Create tokens with IP data when the check is enabled
- Restart SSO flows after changing security configuration
When it happens
Trigger: assert()/assertAndConsume() runs with Configure 'passbolt.security.userIp' = true and the token data has no DATA_IP entry — tokens created with IP binding disabled (or before the feature) but asserted with it enabled, or corrupted/truncated token data.
Common situations: Config change between token creation and consumption (security.userIp turned on after tokens were minted without IP data); manually crafted tokens in tests; data JSON loss during a manual DB edit or restore.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- The SSO authentication token is invalid. User agent is…
- SSO settings edit endpoints are disabled.
- The SSO authentication token is invalid. Settings id is…
- Access to this service requires an invitation. Please…
- AccessToken should be an instance of BaseIdToken class.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/2740726c32d5b505.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/Sso/src/Service/SsoAuthenticationTokens/SsoAuthenticationTokenGetService.php:191
if ($token->isExpired()) {
throw new BadRequestException($errorMsg . __('The authentication token is expired.'));
}
try {
$sid = $token->getDataProperty(SsoAuthenticationToken::DATA_SSO_SETTING_ID);
} catch (AuthenticationTokenDataPropertyException $exception) {
throw new BadRequestException($errorMsg . __('Settings id is missing.'), 400, $exception);
}
if ($token->user_id !== $uac->getId() || !Validation::uuid($token->user_id)) {
throw new BadRequestException($errorMsg . __('User id mismatch.'));
}
if (Configure::read('passbolt.security.userIp')) {
try {
$ip = $token->getDataProperty(SsoAuthenticationToken::DATA_IP);
} catch (AuthenticationTokenDataPropertyException $exception) {
throw new BadRequestException($errorMsg . __('Token IP is missing.'), 400, $exception);
}
if ($ip !== $uac->getUserIp()) {
throw new BadRequestException($errorMsg . __('User IP mismatch.'));
}
}
if (Configure::read('passbolt.security.userAgent')) {
try {
$ua = $token->getDataProperty(SsoAuthenticationToken::DATA_USER_AGENT);
} catch (AuthenticationTokenDataPropertyException $exception) {
throw new BadRequestException($errorMsg . __('User agent is missing.'), 400, $exception);
}
if ($ua !== $uac->getUserAgent()) {
throw new BadRequestException($errorMsg . __('User agent mismatch.'));
}
}
View on GitHub (pinned to 31c1bbc10f)