Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1371,8 +1371,7 @@ protected String getUIDIfExists(JSONObject object) {
public String getSelectorSingle(OperationOptions options) {

if (options != null) {

return selector(getSchemaTranslator().filter(ObjectClass.ACCOUNT_NAME, options,
String[] filtered = getSchemaTranslator().filter(ObjectClass.ACCOUNT_NAME, options,
ATTR_ACCOUNTENABLED, ATTR_DISPLAYNAME,
ATTR_ONPREMISESIMMUTABLEID, ATTR_MAILNICKNAME, ATTR_USERPRINCIPALNAME, ATTR_ABOUTME,
ATTR_BIRTHDAY, ATTR_BUSINESSPHONES, ATTR_CITY, ATTR_COMPANYNAME, ATTR_COUNTRY, ATTR_DEPARTMENT,
Expand All @@ -1387,7 +1386,23 @@ public String getSelectorSingle(OperationOptions options) {
ATTR_EXTERNALUSERSTATE, ATTR_EXTERNALUSERSTATECHANGEDATETIME, ATTR_MANAGER,
ATTR_EMPLOYEE_HIRE_DATE, ATTR_EMPLOYEE_LEAVE_DATE_TIME, ATTR_EMPLOYEE_TYPE,
ATTR_FAX_NUMBER, ATTR_EMPLOYEE_ID, ATTR_ONPREMISESEXTENSIONATTRIBUTES
));
);

// Exclude SPO attributes unless they were explicitly requested via attributesToGet.
// SPO attributes (aboutMe, mySite, birthday, etc.) require a SharePoint Online license;
// including them in $select causes HTTP 400 on tenants without SPO.
// When SchemaTranslator.filter() falls back to returning all candidates (because
// attributesToGet is empty), SPO attributes leak into $select unintentionally.
String[] explicitAttrs = options.getAttributesToGet();
Set<String> explicitlyRequested = explicitAttrs != null
? new HashSet<>(Arrays.asList(explicitAttrs))
: Collections.emptySet();

filtered = Arrays.stream(filtered)
.filter(attr -> !SPO_ATTRS.contains(attr) || explicitlyRequested.contains(attr))
.toArray(String[]::new);

return selector(filtered);
} else {

return selector(
Expand Down