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

coheigea pushed a commit to branch coheigea/userinfo
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 1d41d8b91bfccc9ef265dcd763e563dd8937f41a
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Fri Jul 10 15:04:15 2026 +0100

    Filter claims by granted scopes for the IdToken case
---
 .../cxf/rs/security/oidc/idp/UserInfoService.java  | 40 ++++++++---
 .../rs/security/oidc/idp/UserInfoServiceTest.java  | 82 ++++++++++++++++++++++
 2 files changed, 113 insertions(+), 9 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..04e1bb7125c 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,29 @@ public class UserInfoService extends 
OAuthServerJoseJwtProducer {
             userInfo.setIssuer(idToken.getIssuer());
             userInfo.setAudience(idToken.getAudience());
         }
-        if (idToken.getPreferredUserName() != null) {
+        if (scopes.contains(OidcUtils.PROFILE_SCOPE) && 
idToken.getPreferredUserName() != null) {
             userInfo.setPreferredUserName(idToken.getPreferredUserName());
         }
-        if (idToken.getName() != null) {
+        if (scopes.contains(OidcUtils.PROFILE_SCOPE) && idToken.getName() != 
null) {
             userInfo.setName(idToken.getName());
         }
-        if (idToken.getGivenName() != null) {
+        if (scopes.contains(OidcUtils.PROFILE_SCOPE) && idToken.getGivenName() 
!= null) {
             userInfo.setGivenName(idToken.getGivenName());
         }
-        if (idToken.getFamilyName() != null) {
+        if (scopes.contains(OidcUtils.PROFILE_SCOPE) && 
idToken.getFamilyName() != null) {
             userInfo.setFamilyName(idToken.getFamilyName());
         }
-        if (idToken.getEmail() != null) {
+        if (scopes.contains(OidcUtils.EMAIL_SCOPE) && idToken.getEmail() != 
null) {
             userInfo.setEmail(idToken.getEmail());
         }
-        if (idToken.getNickName() != null) {
+        if (scopes.contains(OidcUtils.PROFILE_SCOPE) && 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 +142,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