This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch 4.1.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/4.1.x-fixes by this push:
     new 1e46205fe69 Filter claims by granted scopes for the IdToken case 
(#3304)
1e46205fe69 is described below

commit 1e46205fe693ace09baf6973cf6f75c48c3b1af9
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Fri Jul 17 16:18:28 2026 +0100

    Filter claims by granted scopes for the IdToken case (#3304)
    
    (cherry picked from commit c409f44cd712c9d5fbdfbc24860f73445c186ae1)
---
 .../cxf/rs/security/oidc/idp/UserInfoService.java  | 60 +++++++++++-----
 .../rs/security/oidc/idp/UserInfoServiceTest.java  | 82 ++++++++++++++++++++++
 2 files changed, 124 insertions(+), 18 deletions(-)

diff --git 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/UserInfoService.java
 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/UserInfoService.java
index 4ca4795e3fe..479dcdd9688 100644
--- 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/UserInfoService.java
+++ 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/UserInfoService.java
@@ -53,6 +53,7 @@ public class UserInfoService extends 
OAuthServerJoseJwtProducer {
     @Produces({"application/json", "application/jwt" })
     public Response getUserInfo() {
         OAuthContext oauth = OAuthContextUtils.getContext(mc);
+        List<String> scopes = 
OAuthUtils.convertPermissionsToScopeList(oauth.getPermissions());
 
         // Check the access token has the "openid" scope
         if (!oauth.getPermissions().stream()
@@ -64,12 +65,12 @@ public class UserInfoService extends 
OAuthServerJoseJwtProducer {
         UserInfo userInfo = null;
         if (userInfoProvider != null) {
             userInfo = userInfoProvider.getUserInfo(oauth.getClientId(), 
oauth.getSubject(),
-                
OAuthUtils.convertPermissionsToScopeList(oauth.getPermissions()));
+                scopes);
         } else if (oauth.getSubject() instanceof OidcUserSubject) {
             OidcUserSubject oidcUserSubject = 
(OidcUserSubject)oauth.getSubject();
             userInfo = oidcUserSubject.getUserInfo();
             if (userInfo == null) {
-                userInfo = createFromIdToken(oidcUserSubject.getIdToken());
+                userInfo = createFromIdToken(oidcUserSubject.getIdToken(), 
scopes);
             }
         }
         if (userInfo == null) {
@@ -98,6 +99,10 @@ public class UserInfoService extends 
OAuthServerJoseJwtProducer {
     }
 
     protected UserInfo createFromIdToken(IdToken idToken) {
+        return createFromIdToken(idToken, Collections.emptyList());
+    }
+
+    protected UserInfo createFromIdToken(IdToken idToken, List<String> scopes) 
{
         UserInfo userInfo = new UserInfo();
         userInfo.setSubject(idToken.getSubject());
 
@@ -105,28 +110,31 @@ public class UserInfoService extends 
OAuthServerJoseJwtProducer {
             userInfo.setIssuer(idToken.getIssuer());
             userInfo.setAudience(idToken.getAudience());
         }
-        if (idToken.getPreferredUserName() != null) {
-            userInfo.setPreferredUserName(idToken.getPreferredUserName());
-        }
-        if (idToken.getName() != null) {
-            userInfo.setName(idToken.getName());
-        }
-        if (idToken.getGivenName() != null) {
-            userInfo.setGivenName(idToken.getGivenName());
-        }
-        if (idToken.getFamilyName() != null) {
-            userInfo.setFamilyName(idToken.getFamilyName());
+        if (scopes.contains(OidcUtils.PROFILE_SCOPE)) {
+            if (idToken.getPreferredUserName() != null) {
+                userInfo.setPreferredUserName(idToken.getPreferredUserName());
+            }
+            if (idToken.getName() != null) {
+                userInfo.setName(idToken.getName());
+            }
+            if (idToken.getGivenName() != null) {
+                userInfo.setGivenName(idToken.getGivenName());
+            }
+            if (idToken.getFamilyName() != null) {
+                userInfo.setFamilyName(idToken.getFamilyName());
+            }
+            if (idToken.getNickName() != null) {
+                userInfo.setNickName(idToken.getNickName());
+            }
         }
-        if (idToken.getEmail() != null) {
+        if (scopes.contains(OidcUtils.EMAIL_SCOPE) && idToken.getEmail() != 
null) {
             userInfo.setEmail(idToken.getEmail());
         }
-        if (idToken.getNickName() != null) {
-            userInfo.setNickName(idToken.getNickName());
-        }
 
         if (additionalClaims != null && !additionalClaims.isEmpty()) {
             for (String additionalClaim : additionalClaims) {
-                if (idToken.containsProperty(additionalClaim)) {
+                if (idToken.containsProperty(additionalClaim)
+                    && isClaimExposedByScope(additionalClaim, scopes)) {
                     userInfo.setClaim(additionalClaim, 
idToken.getClaim(additionalClaim));
                 }
             }
@@ -136,6 +144,22 @@ public class UserInfoService extends 
OAuthServerJoseJwtProducer {
         return userInfo;
     }
 
+    private boolean isClaimExposedByScope(String claimName, List<String> 
scopes) {
+        if (OidcUtils.PROFILE_CLAIMS.contains(claimName)) {
+            return scopes.contains(OidcUtils.PROFILE_SCOPE);
+        }
+        if (OidcUtils.EMAIL_CLAIMS.contains(claimName)) {
+            return scopes.contains(OidcUtils.EMAIL_SCOPE);
+        }
+        if (OidcUtils.ADDRESS_CLAIMS.contains(claimName)) {
+            return scopes.contains(OidcUtils.ADDRESS_SCOPE);
+        }
+        if (OidcUtils.PHONE_CLAIMS.contains(claimName)) {
+            return scopes.contains(OidcUtils.PHONE_SCOPE);
+        }
+        return true;
+    }
+
     public void setUserInfoProvider(UserInfoProvider userInfoProvider) {
         this.userInfoProvider = userInfoProvider;
     }
diff --git 
a/rt/rs/security/sso/oidc/src/test/java/org/apache/cxf/rs/security/oidc/idp/UserInfoServiceTest.java
 
b/rt/rs/security/sso/oidc/src/test/java/org/apache/cxf/rs/security/oidc/idp/UserInfoServiceTest.java
new file mode 100644
index 00000000000..2c02a1f0e74
--- /dev/null
+++ 
b/rt/rs/security/sso/oidc/src/test/java/org/apache/cxf/rs/security/oidc/idp/UserInfoServiceTest.java
@@ -0,0 +1,82 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.oidc.idp;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.apache.cxf.rs.security.oidc.common.IdToken;
+import org.apache.cxf.rs.security.oidc.common.UserInfo;
+import org.apache.cxf.rs.security.oidc.utils.OidcUtils;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class UserInfoServiceTest {
+
+    @Test
+    public void testCreateFromIdTokenFiltersClaimsForOpenIdScope() {
+        UserInfoService service = new UserInfoService();
+        
service.setAdditionalClaims(Collections.singletonList("email_verified"));
+
+        IdToken idToken = new IdToken();
+        idToken.setSubject("alice");
+        idToken.setName("Alice Example");
+        idToken.setEmail("[email protected]");
+        idToken.setEmailVerified(true);
+        idToken.setGivenName("Alice");
+        idToken.setFamilyName("Example");
+
+        UserInfo userInfo = service.createFromIdToken(idToken, 
Collections.singletonList(OidcUtils.OPENID_SCOPE));
+
+        assertEquals("alice", userInfo.getSubject());
+        assertNull(userInfo.getName());
+        assertNull(userInfo.getEmail());
+        assertNull(userInfo.getGivenName());
+        assertNull(userInfo.getFamilyName());
+        assertNull(userInfo.getEmailVerified());
+        assertNull(userInfo.getPhoneNumber());
+    }
+
+    @Test
+    public void 
testCreateFromIdTokenReturnsProfileAndEmailClaimsForGrantedScopes() {
+        UserInfoService service = new UserInfoService();
+        
service.setAdditionalClaims(Collections.singletonList("email_verified"));
+
+        IdToken idToken = new IdToken();
+        idToken.setSubject("alice");
+        idToken.setName("Alice Example");
+        idToken.setEmail("[email protected]");
+        idToken.setEmailVerified(true);
+        idToken.setGivenName("Alice");
+        idToken.setFamilyName("Example");
+
+        UserInfo userInfo = service.createFromIdToken(idToken,
+            Arrays.asList(OidcUtils.OPENID_SCOPE, OidcUtils.PROFILE_SCOPE, 
OidcUtils.EMAIL_SCOPE));
+
+        assertEquals("alice", userInfo.getSubject());
+        assertEquals("Alice Example", userInfo.getName());
+        assertEquals("[email protected]", userInfo.getEmail());
+        assertEquals("Alice", userInfo.getGivenName());
+        assertEquals("Example", userInfo.getFamilyName());
+        assertEquals(Boolean.TRUE, userInfo.getEmailVerified());
+    }
+}
\ No newline at end of file

Reply via email to