Skip to content

Fix external OAuth role mapping regression in v78#3814

Closed
ybykov-a9s wants to merge 1 commit intocloudfoundry:developfrom
ybykov-a9s:fix/v78-external-oauth-roles-regression
Closed

Fix external OAuth role mapping regression in v78#3814
ybykov-a9s wants to merge 1 commit intocloudfoundry:developfrom
ybykov-a9s:fix/v78-external-oauth-roles-regression

Conversation

@ybykov-a9s
Copy link
Copy Markdown
Contributor

Summary

This PR fixes a backward-compatibility regression introduced in v78 where token role content for external OAuth or OIDC users changed from mapped internal UAA authorities to raw upstream IdP groups.

Before this change:

  • externalGroups was populated from raw external authorities
  • downstream token role content could mirror user attributes roles from the IdP groups claim

After this change:

  • externalGroups is populated from mapped internal authorities
  • token role semantics match pre-upgrade behavior from v77

Problem

After upgrading from v77.35.0 to v78.6.0, role-related token content changed:

  • expected: mapped internal authorities such as cloud_controller.audit
  • actual: raw external groups from the IdP, often duplicating user attributes roles content

This is a behavior regression, not a field ordering issue.

Root Cause

In ExternalOAuthAuthenticationManager.populateAuthenticationAttributes, externalGroups was built from authenticationData.externalAuthorities, which contains raw groups from the IdP.

That value is later persisted and reused in token construction paths, causing raw groups to appear where mapped internal authorities were expected.

Fix

Use authenticationData.authorities, which contains mapped internal authorities, when populating externalGroups.
In short:

  • from: externalAuthorities (raw)
  • to: authorities (mapped)

Why this is correct

  • Preserves established v77 token role semantics
  • Keeps raw IdP groups separate from mapped internal authorization output
  • Avoids compatibility break for consumers expecting internal UAA authority values

Tests

Added or updated focused regression coverage in ExternalOAuthAuthenticationManagerTest to verify:

  • externalGroups is derived from mapped authorities
  • raw external groups are not used for externalGroups in this path

Targeted test execution:

  • module tests passed for the focused regression scenario on v78 code path

Compatibility Impact

This change restores prior behavior and reduces upgrade risk for installations relying on mapped internal authorities in token role content.

Issue

Fixes issue

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Restores pre-v78 behavior for external OAuth/OIDC users by ensuring externalGroups on UaaAuthentication is derived from mapped internal UAA authorities (not raw upstream IdP groups), preserving backward-compatible token role semantics.

Changes:

  • Populate UaaAuthentication.externalGroups from authenticationData.authorities (mapped/internal) instead of authenticationData.externalAuthorities (raw/upstream).
  • Update/add a focused regression test asserting externalGroups comes from mapped authorities and excludes raw external groups.

Reviewed changes

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

File Description
server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java Fixes populateAuthenticationAttributes to source externalGroups from mapped authorities to restore v77 token role semantics.
server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerTest.java Renames and adjusts the regression test to validate the corrected externalGroups source.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@duanemay
Copy link
Copy Markdown
Member

duanemay commented Apr 7, 2026

This was an intentional change eaf1b64 @fhanik

The jwt-bearer grant confuses the internal (mapped) authorities(scopes) from the incoming(external) groups

@strehle
Copy link
Copy Markdown
Member

strehle commented Apr 7, 2026

@duanemay My main concern is, that we dont have any Integration Test which would found the change before and also this PR has no effects on ITs

@strehle strehle requested a review from a team April 8, 2026 18:43
@strehle
Copy link
Copy Markdown
Member

strehle commented Apr 8, 2026

About my testings.

I setup a similar env to check what was our behaviour in 77.35 and now. Problem is and was that we had a different behaviour for SAML and OIDC.

In SAML the roels in id_token was always the external groups in OIDC it was the mapped version.
With eaf1b64 this was synchronized, so that SAML and OIDC are equal in id and access token.

Problem is: the behaviour in OIDC is not only in 77.35 like this but a long time and maybe adopted from LDAP behaviour,
a09f3bd

@fhanik any thoughts ?

From my side we can accept this PR and then need an Integration tests to fix this behaviour to OIDC

@github-project-automation github-project-automation bot moved this from Inbox to Pending Merge | Prioritized in Foundational Infrastructure Working Group Apr 8, 2026
@strehle strehle requested a review from a team April 8, 2026 18:48
@fhanik
Copy link
Copy Markdown
Contributor

fhanik commented Apr 9, 2026

Let me take a look again. The change in v78 was intentional. @strehle @duanemay . Reverting that change will break token exchange and how authorities are mapped.

@fhanik
Copy link
Copy Markdown
Contributor

fhanik commented Apr 9, 2026

As I'm reviewing this, here is what I have found

The change proposed does change the intended behavior relative to SAML and LDAP.

Before (using getExternalAuthorities()):
externalGroups on the OAuth UaaAuthentication would hold IdP-side group strings (after allowlist), same role as SAML’s filterSamlAuthorities / LDAP’s getExternalUserAuthorities.

After (using getAuthorities()):
externalGroups is filled with mapped UAA role names — the same kind of strings that already drive UaaAuthentication.getAuthorities() for that user (from authenticationData.getAuthorities() in getUser).

The modification collapses the usual split: elsewhere externalGroups = external, authorities = internal/mapped; with getAuthorities()

While this code may have been alive for quite some time (years), it is still a bug, as group mapping should be consistent across all IDP.

I'm inclined to introduce a configuration option that would allow an installation to have to old behavior (bug in place) with the default being that UAA is aligned with the same group mapping behavior regardless of IDP type or grant type.

@ybykov-a9s @strehle Thoughts?

@fhanik
Copy link
Copy Markdown
Contributor

fhanik commented Apr 9, 2026

I have provided a proposed solution in #3821

Copy link
Copy Markdown
Contributor

@fhanik fhanik left a comment

Choose a reason for hiding this comment

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

Review PR #3821 to see if that will suffice to allow opt in to previous versions behavior

#3821

@github-project-automation github-project-automation bot moved this from Pending Merge | Prioritized to Waiting for Changes | Open for Contribution in Foundational Infrastructure Working Group Apr 9, 2026
fhanik added a commit that referenced this pull request Apr 10, 2026
…es-behavior

OAuth Group Mapping Behavior - Combine #3814 and #3820
@fhanik
Copy link
Copy Markdown
Contributor

fhanik commented Apr 10, 2026

Closed. Merged in #3821

@fhanik fhanik closed this Apr 10, 2026
@github-project-automation github-project-automation bot moved this from Waiting for Changes | Open for Contribution to Done in Foundational Infrastructure Working Group Apr 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

Regression after v78 upgrade: external OAuth token roles use raw IdP groups instead of mapped UAA authorities

5 participants