Skip to content

feat(sso): sso mapping teant scoped (#6370)#6371

Open
corinnekrych wants to merge 12 commits into
mainfrom
issue-6370/sso-mapping
Open

feat(sso): sso mapping teant scoped (#6370)#6371
corinnekrych wants to merge 12 commits into
mainfrom
issue-6370/sso-mapping

Conversation

@corinnekrych

@corinnekrych corinnekrych commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Proposed changes

This pull request refactors and enhances the SSO group mapping logic in UserMappingService, improving configurability, maintainability, and test coverage. The main changes include extracting provider property reading logic into a new helper class, supporting group scoping (tenant/platform) via configuration, and adding comprehensive unit tests.

SSO Group Mapping Improvements:

  • Refactored UserMappingService to use a new ReadPropertiesHelper for reading provider configuration0)
  • Enhanced group mapping logic to support scoping groups to either tenant, platform, or both, based on the new user_scope property per provider. The mapping now handles auto-creation of groups in the correct scope and removes groups when users are removed from the IDP.

Testing Instructions

  • login ad admin user, create anew tenant A copy the TenantId
  • Modified application.properties (or application-dev.properties) with
openaev.provider.microsoft.tenant_id=<TenantId>
openaev.provider.microsoft.user_scope=platform,tenant
openaev.provider.microsoft.groups_management=[{"idpGroup": "Filigran","userGroup": "GROUP_A","autoCreate": true}]
  • restart OAEV
  • login with corporate microsoft login
  • logout
  • login as admin,
  • GROUP_A was created as tenant group
  • GROUP_A was created as patform group
  • change config to:
openaev.provider.microsoft.tenant_id=<TenantId>
openaev.provider.microsoft.user_scope=tenant
openaev.provider.microsoft.groups_management=[{"idpGroup": "Filigran","userGroup": "GROUP_B","autoCreate": true}]
  • restart OAEV
  • login with corporate microsoft login
  • logout
  • login as admin,
  • check user was created as tenant user
  • GROUP_B was created as tenant group

Related issues

Checklist

  • I consider the submitted work as finished
  • I tested the code for its functionality
  • I wrote test cases for the relevant uses case
  • I added/update the relevant documentation (either on github or on notion)
  • Where necessary I refactored code to improve the overall quality
  • For bug fix -> I implemented a test that covers the bug

Further comments

If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...

Copilot AI review requested due to automatic review settings June 24, 2026 11:39
@github-actions github-actions Bot added the filigran team Item from the Filigran team. label Jun 24, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the SSO group-mapping flow to support tenant-scoped group lookup/auto-creation by resolving an effective tenantId (mapping-level tenantId overrides provider-level openaev.provider.<registrationId>.tenant_id). It also adjusts call sites and adds regression tests for “multiple IdP groups map to the same OpenAEV group” behavior and removal semantics.

Changes:

  • Extend UserMappingService.mapCurrentUserWithGroup(...) to accept registrationId and resolve an effective tenant for group lookup / auto-create / user tenant attachment.
  • Update SecurityService to call the new UserMappingService signature.
  • Add new UserMappingServiceTest coverage for multiple mappings targeting the same user group and for removal behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
openaev-api/src/main/java/io/openaev/service/UserMappingService.java Adds tenant-aware group lookup/creation and improves mapping/removal behavior (but current implementation has tenant-scope correctness issues).
openaev-api/src/main/java/io/openaev/config/security/SecurityService.java Updates call to the new mapCurrentUserWithGroup method signature.
openaev-api/src/test/java/io/openaev/sso/UserMappingServiceTest.java Updates existing tests for new signature and adds new tests for multi-mapping and removal scenarios.
Comments suppressed due to low confidence (2)

openaev-api/src/main/java/io/openaev/service/UserMappingService.java:84

  • issue (blocking): The existing-group check deduplicates by group name, but groups are dual-scope and names may collide across tenants/platform. This can lead to skipping a needed add or adding duplicates incorrectly. Prefer using entity equality (id-based equals/hashCode) via userGroups.contains(group) instead of comparing names.
            List<Group> userGroups = user.getUnscopedGroups();
            List<Group> existing =
                userGroups.stream()
                    .filter(userG -> userG.getName().equals(groupOptional.get().getName()))
                    .toList();
            if (existing.isEmpty()) {
              userGroups.add(groupOptional.get());
              user.setGroups(userGroups);
            }

openaev-api/src/main/java/io/openaev/service/UserMappingService.java:123

  • issue (blocking): The removal logic and the "anyMappingMatchesForSameGroup" check are based only on userGroup name, ignoring tenant scoping. With dual-scope groups, this can remove (or keep) the wrong group when the same name exists in multiple tenants/platform, and it can also prevent removal because a different-tenant mapping matched. Include the effective tenantId in both the "matches" computation and the group-to-remove predicate.
      boolean anyMappingMatchesForSameGroup =
          groupMappings.stream()
              .filter(m -> m.getUserGroup().equals(mapping.getUserGroup())) // do we have several mapping with same group
              .anyMatch(m -> groupsFromToken.contains(m.getIdpGroup()));
      if (!anyMappingMatchesForSameGroup
          && user.getUnscopedGroups().stream()
              .anyMatch(groupOfUser -> groupOfUser.getName().equals(mapping.getUserGroup()))) {
        // It means the user was removed from the group in the identity provider -> we remove it
        // from its current groups
        List<Group> userGroups = user.getUnscopedGroups();
        userGroups.removeIf(group -> group.getName().equals(mapping.getUserGroup()));
        user.setGroups(userGroups);

Comment thread openaev-api/src/main/java/io/openaev/service/UserMappingService.java Outdated
Comment thread openaev-api/src/main/java/io/openaev/service/UserMappingService.java Outdated
Comment thread openaev-api/src/test/java/io/openaev/sso/UserMappingServiceTest.java Outdated
@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 82.14286% with 20 lines in your changes missing coverage. Please review.
✅ Project coverage is 45.22%. Comparing base (1f6fb02) to head (bb68402).

Files with missing lines Patch % Lines
...in/java/io/openaev/service/UserMappingService.java 81.11% 7 Missing and 10 partials ⚠️
...io/openaev/service/utils/ReadPropertiesHelper.java 85.00% 0 Missing and 3 partials ⚠️

❌ Your project check has failed because the head coverage (2.99%) is below the target coverage (80.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #6371      +/-   ##
============================================
+ Coverage     45.14%   45.22%   +0.07%     
- Complexity     7755     7786      +31     
============================================
  Files          2332     2333       +1     
  Lines         64652    64729      +77     
  Branches       8554     8571      +17     
============================================
+ Hits          29188    29272      +84     
+ Misses        33610    33590      -20     
- Partials       1854     1867      +13     
Flag Coverage Δ
backend 67.27% <82.14%> (+0.04%) ⬆️
e2e 18.74% <ø> (+0.40%) ⬆️
frontend 2.99% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

}
}
attachTenantFromGroupMapping(mapping, user);
attachTenantToUser(tenantId, user);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we have a bigger problem here, tenant ID in groups_management should not be present. It's a mistake..

https://docs.openaev.io/latest/deployment/authentication/?h=groups_management#map-users-to-groups-automatically-openid-and-saml2

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed reading tenant ID from groups_management in 8c8717f

@corinnekrych
corinnekrych marked this pull request as draft June 25, 2026 13:39
@corinnekrych

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

Copilot AI commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Resolved the merge conflict in UserMappingService.java in commit fix(sso): resolve merge conflict in UserMappingService. The resolution keeps the feature's tenant-scoped group lookup and provider-level tenant resolution from this branch, while adopting the cleaner groupsFromToken.contains(idpGroup) pattern from main. Also fixed the blocking reviewer issue: added existsById validation before getReferenceById in the autoCreate path.

@corinnekrych
corinnekrych marked this pull request as ready for review July 10, 2026 08:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

filigran team Item from the Filigran team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🔐 [SSO improv - Phase 0] tenant scope sso mapping for auth/saml configuration

4 participants