Overview
The Groups feature enables administrators to efficiently manage user–project relationships and user-role assignment. Groups feature can be used independent of SCIM or integrated with SCIM.
Requirements for Displaying Groups UI and Accessing Groups APIs
Permissions
Access to the Groups area of the UI and most Groups module actions is controlled by these permissions:
- GROUPS_ADMINISTRATE – Create/delete groups; full access to list, group detail, group users, and group projects. Used for
create_groupanddelete_group, and together with the next permission for read operations. - GROUPS_MANAGE_MEMBERSHIP – Add/remove users in a group, view groups (list, detail,
get_group_users,get_group_projects, etc.) when not already covered by administrate. - GROUPS_LINK_TO_PROJECTS – Link or unlink a group to a project (assign group to project / remove group from project), subject to the project rules below. This is separate from administrate: a user can hold GROUPS_LINK_TO_PROJECTS without GROUPS_ADMINISTRATE and still assign groups to projects if they may edit that project.
A user with GROUPS_ADMINISTRATE or GROUPS_MANAGE_MEMBERSHIP can:
- See the Groups tab on the Users page.
- Open Group detail at
{basePath}/nui/groups/:id(e.g./nui/groups/:idwhen the webappbasePathis empty; there is no/users/segment in this path). - See View project groups in the project menu and open project groups at
{basePath}/nui/project/:projectId/groups.
A user with USERS_VIEW_ACCESS or when viewing their own profile can see the Groups section on a user profile (list of groups the user belongs to). That visibility is UI-only; see the API table below for get_user_groups.
Assigning a group to a project (assign_group / remove) requires permission to act on the project: PROJECT_UPDATE_ANY, or GROUPS_LINK_TO_PROJECTS, or the current user is the project creator. The project must still be resolved and accessible to the user.
Summary
| Element / API | Requirement |
|---|---|
| Groups tab (Users page) | GROUPS_ADMINISTRATE or GROUPS_MANAGE_MEMBERSHIP |
| Group detail route | GROUPS_ADMINISTRATE or GROUPS_MANAGE_MEMBERSHIP |
| User profile – Groups card (UI) | USERS_VIEW_ACCESS or own profile |
| Project – View project groups (UI) | GROUPS_ADMINISTRATE or GROUPS_MANAGE_MEMBERSHIP |
| Link / unlink group ↔ project (UI) | GROUPS_LINK_TO_PROJECTS (and project rules in the handler) |
| Typical Groups module APIs (list, info, add/remove user, group users, group projects, …) | GROUPS_ADMINISTRATE and/or GROUPS_MANAGE_MEMBERSHIP per handler |
get_user_groups |
Authenticated; no GROUPS_* check in handler |
get_project_groups |
Project access (not GROUPS_*) |
assign_group / remove_group |
GROUPS_LINK_TO_PROJECTS and/or project update / creator, etc. |
No dependency on webapp_scim_enabled for showing the Groups UI and using the internal Groups APIs: access is determined by the rules above, not by SCIM being on or off (except for optional external_id on create when SCIM is off).
SCIM API: Group resource id format
When integrating with SCIM v2 Groups (/scim/v2/Groups, etc.), treat the Group id as a string in a fixed format:
- Format:
group-<id>where<id>is the numeric primary key of the group in thescim_groupstable (same value Workbench uses internally as the group id). - Where it appears: In SCIM JSON responses as the
idfield, and inmeta.location(e.g.…/scim/v2/Groups/group-42). List/filter responses return the same format in eachResources[]entry. - Requests: Use the same
group-<id>value in paths such asGET,PATCH, andDELETE/scim/v2/Groups/group-<id>. For compatibility, a path segment that is only digits (e.g./Groups/42) may still be accepted; prefer the prefixed form for new integrations. - Not SCIM: Non-SCIM Groups APIs and the UI continue to use the numeric
group_idonly. Do not assume SCIM Groupidstrings are valid in internal JSON APIs without stripping thegroup-prefix and using the numeric part.
This matters for IdP provisioning (e.g. Azure AD / Entra): store and replay the id returned by create/get/list so subsequent PATCH/DELETE target the correct resource.
Role Mapping (webapp_scim_group_role[])
Group-to-role behaviour is optional and configured via webapp_scim_group_role[] in fossid.conf. Implementation: GroupRoleMappingService.
When role mapping is “off” (no role side effects)
If webapp_scim_group_role[] is missing or has no effective entries (no patterns and no default_role###… line that resolves to a real role in the database), the service is not enabled for role changes: add/remove group membership does not add, remove, or replace roles via this feature.
- Add user to group: Only group membership is updated. No roles are assigned or changed by group–role mapping.
- Remove user from group: Only group membership is updated. No roles are changed by group–role mapping, and no default role is applied through this path.
When role mapping is “on”
The service is enabled when it has at least one valid groupNameOrPattern###RoleName mapping or a configured default role line default_role###RoleName (and that role exists in the database). A default-only configuration (no group patterns) can still turn on the branch that runs when a user’s last group is removed (see below).
Role accumulation (multiple roles)
- Multiple roles per user: When a user belongs to multiple groups, they accumulate roles from all groups. Each group (that matches a mapping) contributes its role; the user ends up with the union of those roles.
- No role override: Adding a user to a new group does not strip roles from other groups; a role is appended if the user does not already have it (for that mapped role).
Example: A user in cld-OU-X-contributors-sg (CustomContributors) and cld-OU-Y-readers-sg (CustomReaders) can have both roles if both groups match mappings.
Role removal when leaving a group
When a user is removed from a group and mapping is enabled:
- Check other groups: The system checks whether the user is in any other group that maps to the same role as the group they left.
- Conditional removal of that role:
- If the user is not in another group with the same mapped role → that role is removed from the user.
- If the user is in another group that maps to the same role → that role is kept.
No remaining groups → default role
If, after removal, the user has no group memberships left, the implementation removes all role assignments for that user in user_roles and then assigns a single default role (if a default role ID can be resolved).
- The configured
default_role###Nameinfossid.confis used when present and valid. If no default is configured, the service falls back to the role nameLicensing Officerwhen resolving the default role ID (for this path). - This is a full replacement of the user’s roles in that step—not “only group-derived” roles. Operators should be aware of this behaviour.
Example scenarios
| Scenario | Result |
|---|---|
| User added to “Engineering-contributors-sg” then “Product-readers-sg” | User can have both mapped roles (accumulation). |
| User in both groups; removed from “Engineering-contributors-sg” | User keeps the other group’s role if the first group’s role was removed per rules. |
| User in two groups mapping to the same role; removed from one | User keeps the role (still in the other group). |
| User in one group; removed from that group; mapping enabled; no other groups | Mapped role for that group is removed; then all user roles are cleared and default role assigned if resolvable. |
Configuration format (pattern matching, default_role###RoleName, regex) is in GroupRoleMappingService and the implementation plan.
Summary Table
| Scenario | No effective webapp_scim_group_role[] (not enabled) |
Mapping enabled (patterns and/or default role) |
|---|---|---|
| Add user to group | Only membership changes; no role changes | Add to group; may append mapped roles |
| Remove user from group | Only membership changes; no role changes | May remove/keep role by other groups; if no groups left, clear all roles and assign default when configured/resolvable |