passbolt/passbolt_api · critical · Cake\Http\Exception\InternalErrorException
The SCIM secret token expiry configuration is invalid.
Error message
The SCIM secret token expiry configuration is invalid.
What it means
computeExpiredDate() reads the token expiry duration from Configure at 'passbolt.plugins.scim.security.secretToken.expiry' and throws InternalErrorException if the key is not set, since it cannot compute when a newly generated SCIM secret token expires. This is a server misconfiguration (or missing default config), surfaced as a 500 during settings save.
Solutions
- Add the expiry to config/passbolt.php: 'passbolt' => ['plugins' => ['scim' => ['security' => ['secretToken' => ['expiry' => '1 year']]]]] (value must be a string parseable by Date::modify, e.g. '6 months', '90 days').
- Compare with the plugin's default config file (plugins/PassboltEe/Scim/config/config.php) and copy any missing scim keys.
- Clear the config cache (rm tmp/cache/* or `cake cache clear_all`) after editing config files.
Example fix
// before (config/passbolt.php) 'scim' => ['enabled' => true], // after 'scim' => [ 'enabled' => true, 'security' => ['secretToken' => ['expiry' => '1 year']], ],
Defensive patterns
Strategy: validation
Try / catch
try {
$date = $service->computeExpiry();
} catch (InternalErrorException $e) {
Log::alert('Missing passbolt.plugins.scim.security.secretToken.expiry; check config/passbolt.php');
throw $e; // server config issue, do not swallow
} Prevention
- Include the full scim config block (security.secretToken.expiry) in config/passbolt.php on every environment.
- Re-diff config/passbolt.php against the plugin's default config after each passbolt upgrade.
- Smoke-test saving SCIM settings in staging after config changes.
- Clear config caches after editing configure files.
When it happens
Trigger: Creating SCIM settings (POST) or rotating the secret token (PUT with a new token) on a server where passbolt.plugins.scim.security.secretToken.expiry is absent from config/passbolt.php or the loaded configure files.
Common situations: Hand-written passbolt.php missing the newer scim security block; config file not re-deployed after a passbolt upgrade that introduced the expiry setting; typo in the config key path.
Related errors
- Could not save the rbacs, please try again later.
- Could not validate the password policies settings.
- Could not validate the SCIM settings found in database.
- " " is not a valid search filter.
- " " is not a valid search filter. It is not a UTF8 string.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/c39805799e30a139.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/Scim/src/Service/ScimSetSettingsService.php:189
if ($storedHash === null) {
return true;
}
return !ScimTokenVerifier::verify($rawToken, $storedHash);
}
/**
* Compute the expiration date for the SCIM secret token based on the configured expiry duration.
*
* @return string Date in Y-m-d format.
* @throws \Cake\Http\Exception\InternalErrorException If the expiry configuration is invalid.
*/
private function computeExpiredDate(): string
{
/** @var string|null $expiry */
$expiry = Configure::read('passbolt.plugins.scim.security.secretToken.expiry');
if ($expiry === null) {
throw new InternalErrorException(__('The SCIM secret token expiry configuration is invalid.'));
}
return Date::now()->modify('+' . $expiry)->format('Y-m-d');
}
/**
* Generate crypto-secure token for authentication
*
* @return string
* @throws \Exception
*/
public static function generateToken(): string
{
// Generate 256-bit entropy token
$bin = random_bytes(32);
// Base64 gives exact 43 characters (cutting "==" from last)
$token = rtrim(strtr(base64_encode($bin), '+/', '-_'), '=');
View on GitHub (pinned to 31c1bbc10f)