Environment
- GLPI: 11.0.5
- samlsso: 1.2.5
- OS: Ubuntu 24.04 LTS
- IdP: Microsoft Entra ID (Azure AD)
- JIT: Enabled
Problem
When an IdP's SAML response does not include the http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname claim, JIT-created users end up with glpi_users.realname = "0" (the literal string "0") instead of empty/NULL. In our production environment this surfaced as users with "Sobrenome" displaying "0" in the GLPI user list — 7 affected out of ~2340.
This is unrelated to (but discovered while investigating the aftermath of) #90.
Root cause
In src/LoginFlow/User.php around line 473 (and 6 other places), when a claim is missing the code assigns false to the field:
// Surname
if(isset($claims[User::SCHEMA_SURNAME][0])){
if(strlen($claims[User::SCHEMA_SURNAME][0]) <= 255){
$user[User::REALNAME] = $claims[User::SCHEMA_SURNAME][0];
}else{ ... }
}else{
$user[User::REALNAME] = false; // ← bug
}
PHP false in the input array passes through Sanitizer::sanitize() into $user->add() and gets persisted as the string "0" in the varchar(255) NULL DEFAULT NULL column realname. Same pattern repeats for:
| Field |
Line |
Target column |
Visible impact |
| REALNAME |
473 |
glpi_users.realname |
Shows "0" in UI (reported) |
| SAMLJOBTITLE |
486 |
rule input |
Sloppy rule input |
| MOBILE |
499 |
glpi_users.mobile |
Likely same "0" issue |
| PHONE |
512 |
glpi_users.phone |
Likely same "0" issue |
| SAMLCOUNTRY |
525 |
rule input |
Sloppy rule input |
| SAMLCITY |
538 |
rule input |
Sloppy rule input |
| SAMLSTREET |
551 |
rule input |
Sloppy rule input |
Three of these (REALNAME, MOBILE, PHONE) land directly in glpi_users and produce the visible "0" bug.
Expected behavior
When a claim is absent, the corresponding field should be either:
- Not set at all in
$user (falls back to GLPI's default — NULL for these columns), or
- Set to an empty string
"" (also safe: produces empty VARCHAR)
Never false, because PHP's truthy-to-DB casting path inside GLPI's ORM writes it as "0".
Suggested fix
Minimal, surgical — replace = false; with = ""; for each of the 7 fields, or remove the else branches entirely:
// Surname
if(isset($claims[User::SCHEMA_SURNAME][0])){
if(strlen($claims[User::SCHEMA_SURNAME][0]) <= 255){
$user[User::REALNAME] = $claims[User::SCHEMA_SURNAME][0];
}else{ ... }
}
// no else — if claim is absent, leave the field unset (uses column default)
Workaround applied locally
Patched User.php line 473:
- $user[User::REALNAME] = false;
+ $user[User::REALNAME] = "";
Plus SQL cleanup for existing affected rows:
-- Identify affected users
SELECT id, name FROM glpi_users WHERE realname = '0';
-- Fix (after manually verifying correct names):
UPDATE glpi_users SET realname = '<correct_surname>' WHERE id = <id>;
Note
This is a separate bug from #90 (the is_recursive=0 issue), but both were discovered in the same production incident. Happy to open a PR with the full 7-field fix if maintainers prefer.
Environment
Problem
When an IdP's SAML response does not include the
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surnameclaim, JIT-created users end up withglpi_users.realname = "0"(the literal string "0") instead of empty/NULL. In our production environment this surfaced as users with "Sobrenome" displaying "0" in the GLPI user list — 7 affected out of ~2340.This is unrelated to (but discovered while investigating the aftermath of) #90.
Root cause
In
src/LoginFlow/User.phparound line 473 (and 6 other places), when a claim is missing the code assignsfalseto the field:PHP
falsein the input array passes throughSanitizer::sanitize()into$user->add()and gets persisted as the string"0"in thevarchar(255) NULL DEFAULT NULLcolumnrealname. Same pattern repeats for:glpi_users.realnameglpi_users.mobileglpi_users.phoneThree of these (REALNAME, MOBILE, PHONE) land directly in
glpi_usersand produce the visible "0" bug.Expected behavior
When a claim is absent, the corresponding field should be either:
$user(falls back to GLPI's default — NULL for these columns), or""(also safe: produces empty VARCHAR)Never
false, because PHP's truthy-to-DB casting path inside GLPI's ORM writes it as"0".Suggested fix
Minimal, surgical — replace
= false;with= "";for each of the 7 fields, or remove theelsebranches entirely:Workaround applied locally
Patched
User.phpline 473:Plus SQL cleanup for existing affected rows:
Note
This is a separate bug from #90 (the
is_recursive=0issue), but both were discovered in the same production incident. Happy to open a PR with the full 7-field fix if maintainers prefer.