This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cxf.git
The following commit(s) were added to refs/heads/main by this push:
new c409f44cd71 Filter claims by granted scopes for the IdToken case
(#3304)
c409f44cd71 is described below
commit c409f44cd712c9d5fbdfbc24860f73445c186ae1
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)
---
.../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