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 2d8c3c8abea Tighten scope and application_type validation in
DynamicRegistrationService (#3506)
2d8c3c8abea is described below
commit 2d8c3c8abeafb14294d765beb0643fc91e55fcc7
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Fri Sep 25 14:41:45 2026 +0100
Tighten scope and application_type validation in DynamicRegistrationService
(#3506)
---
.../services/DynamicRegistrationService.java | 13 ++++++++-
.../services/DynamicRegistrationServiceTest.java | 33 ++++++++++++++++++++++
2 files changed, 45 insertions(+), 1 deletion(-)
diff --git
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java
index ecb4847e8ad..5bf67cae103 100644
---
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java
+++
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java
@@ -20,6 +20,7 @@ package org.apache.cxf.rs.security.oauth2.services;
import java.net.URI;
import java.security.cert.X509Certificate;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -270,6 +271,9 @@ public class DynamicRegistrationService {
String appType = request.getApplicationType();
if (appType == null) {
appType = DEFAULT_APPLICATION_TYPE;
+ } else if (!WEB_APPLICATION_TYPE.equalsIgnoreCase(appType)
+ && !NATIVE_APPLICATION_TYPE.equalsIgnoreCase(appType)) {
+ reportInvalidRequestError(new OAuthError(INVALID_CLIENT_METADATA,
"Unsupported application type"));
}
boolean isConfidential = DEFAULT_APPLICATION_TYPE.equals(appType)
&& (passwordRequired
@@ -394,6 +398,10 @@ public class DynamicRegistrationService {
List<String> requestedScopes = OAuthUtils.parseScope(scope);
validateClientScopes(requestedScopes);
client.setRegisteredScopes(requestedScopes);
+ } else if (allowedClientScopes != null &&
client.getRegisteredScopes().isEmpty()) {
+ // An empty list of registered scopes allows any scope to be
requested later on,
+ // so restrict the client to the configured scopes instead
+ client.setRegisteredScopes(new ArrayList<>(allowedClientScopes));
}
// Client Application URI
String clientUri = request.getClientUri();
@@ -466,6 +474,9 @@ public class DynamicRegistrationService {
reportInvalidRequestError(new
OAuthError(INVALID_CLIENT_METADATA,
"Unsupported redirect URI hostname for scheme"));
}
+ } else {
+ reportInvalidRequestError(new OAuthError(INVALID_CLIENT_METADATA,
+ "Unsupported application type"));
}
}
@@ -533,7 +544,7 @@ public class DynamicRegistrationService {
List<String> allowedScopes = allowedClientScopes;
if (allowedScopes == null && clientProvider instanceof
AbstractOAuthDataProvider) {
- allowedScopes = new java.util.ArrayList<>(
+ allowedScopes = new ArrayList<>(
((AbstractOAuthDataProvider)clientProvider).getPermissionMap().keySet());
}
diff --git
a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationServiceTest.java
b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationServiceTest.java
index 3bfaceafffa..1b5593ad74f 100644
---
a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationServiceTest.java
+++
b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationServiceTest.java
@@ -90,6 +90,39 @@ public class DynamicRegistrationServiceTest {
assertEquals(Collections.singletonList("openid"),
client.getRegisteredScopes());
}
+ @Test
+ public void testDefaultsToAllowedScopesWhenNoScopeRegistered() {
+ TestDynamicRegistrationService service = new
TestDynamicRegistrationService();
+ service.setAllowedClientScopes(Collections.singletonList("read"));
+
+ Client client = createClient();
+ service.applyClientRegistration(new ClientRegistration(), client);
+
+ assertEquals(Collections.singletonList("read"),
client.getRegisteredScopes());
+ }
+
+ @Test
+ public void testRejectsUnknownApplicationTypeRedirectUrl() {
+ TestDynamicRegistrationService service = new
TestDynamicRegistrationService();
+
+ ClientRegistration request = new ClientRegistration();
+ request.setApplicationType("x");
+ request.setRedirectUris(List.of("http://evil.example/cb"));
+
+ Client client = createClient();
+
client.setAllowedGrantTypes(Collections.singletonList(OAuthConstants.IMPLICIT_GRANT));
+ assertThrows(BadRequestException.class, () ->
service.applyClientRegistration(request, client));
+ }
+
+ @Test
+ public void testRejectsUnknownApplicationType() {
+ TestDynamicRegistrationService service = new
TestDynamicRegistrationService();
+
+ ClientRegistration request = new ClientRegistration();
+ request.setApplicationType("x");
+ assertThrows(BadRequestException.class, () ->
service.createClient(request));
+ }
+
@Test
public void testAcceptsAllowedRedirectUrlsWebApp() {
TestDynamicRegistrationService service = new
TestDynamicRegistrationService();