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 02b8e46137a Fix the OAuth2 client ip address check and add a test
(#3127)
02b8e46137a is described below
commit 02b8e46137a0c628d4daa93bda235949b2eb5ab2
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Thu May 21 07:41:17 2026 +0100
Fix the OAuth2 client ip address check and add a test (#3127)
---
.../oauth2/filters/OAuthRequestFilter.java | 2 +-
.../oauth2/common/JCacheOAuthDataProviderImpl.java | 54 +++++++++++++-------
.../oauth2/filters/OAuth2JwtFiltersTest.java | 58 ++++++++++++++++++++--
3 files changed, 93 insertions(+), 21 deletions(-)
diff --git
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java
index 68a4ada20c5..0f5d8a04e62 100644
---
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java
+++
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java
@@ -138,7 +138,7 @@ public class OAuthRequestFilter extends
AbstractAccessTokenValidator
if (accessTokenV.getClientIpAddress() != null) {
String remoteAddress =
getMessageContext().getHttpServletRequest().getRemoteAddr();
- if (remoteAddress == null ||
accessTokenV.getClientIpAddress().equals(remoteAddress)) {
+ if (remoteAddress == null ||
!accessTokenV.getClientIpAddress().equals(remoteAddress)) {
String message = "Client IP Address is invalid";
LOG.warning(message);
throw ExceptionUtils.toForbiddenException(null, null);
diff --git
a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/JCacheOAuthDataProviderImpl.java
b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/JCacheOAuthDataProviderImpl.java
index 03e002130d3..d4edc835cfb 100644
---
a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/JCacheOAuthDataProviderImpl.java
+++
b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/JCacheOAuthDataProviderImpl.java
@@ -78,25 +78,10 @@ public class JCacheOAuthDataProviderImpl extends
JCacheCodeDataProvider {
redirectUris.add("https://localhost:" + partnerPort +
"/partnerservice/bookstore/books");
}
client.setRedirectUris(redirectUris);
-
- client.getAllowedGrantTypes().add("authorization_code");
- client.getAllowedGrantTypes().add("refresh_token");
- client.getAllowedGrantTypes().add("implicit");
- client.getAllowedGrantTypes().add("hybrid");
- client.getAllowedGrantTypes().add("password");
- client.getAllowedGrantTypes().add("client_credentials");
-
client.getAllowedGrantTypes().add("urn:ietf:params:oauth:grant-type:saml2-bearer");
-
client.getAllowedGrantTypes().add("urn:ietf:params:oauth:grant-type:jwt-bearer");
-
- client.getRegisteredScopes().add("read_balance");
- client.getRegisteredScopes().add("create_balance");
- client.getRegisteredScopes().add("read_data");
- client.getRegisteredScopes().add("read_book");
- client.getRegisteredScopes().add("create_book");
- client.getRegisteredScopes().add("create_image");
- client.getRegisteredScopes().add("openid");
+ configureDefaultClientGrantsAndScopes(client);
this.setClient(client);
+ addClientIpTestClients(createPublicClients, redirectUris);
// OIDC filters test client
client = createPublicClients ? new Client("consumer-id-oidc", null,
false)
@@ -186,6 +171,41 @@ public class JCacheOAuthDataProviderImpl extends
JCacheCodeDataProvider {
}
}
+ private static void configureDefaultClientGrantsAndScopes(Client client) {
+ client.getAllowedGrantTypes().add("authorization_code");
+ client.getAllowedGrantTypes().add("refresh_token");
+ client.getAllowedGrantTypes().add("implicit");
+ client.getAllowedGrantTypes().add("hybrid");
+ client.getAllowedGrantTypes().add("password");
+ client.getAllowedGrantTypes().add("client_credentials");
+
client.getAllowedGrantTypes().add("urn:ietf:params:oauth:grant-type:saml2-bearer");
+
client.getAllowedGrantTypes().add("urn:ietf:params:oauth:grant-type:jwt-bearer");
+
+ client.getRegisteredScopes().add("read_balance");
+ client.getRegisteredScopes().add("create_balance");
+ client.getRegisteredScopes().add("read_data");
+ client.getRegisteredScopes().add("read_book");
+ client.getRegisteredScopes().add("create_book");
+ client.getRegisteredScopes().add("create_image");
+ client.getRegisteredScopes().add("openid");
+ }
+
+ private void addClientIpTestClients(boolean createPublicClients,
List<String> redirectUris) {
+ Client ipPassClient = createPublicClients ? new
Client("consumer-id-ip-pass", null, false)
+ : new Client("consumer-id-ip-pass", "this-is-a-secret", true);
+ ipPassClient.setRedirectUris(new ArrayList<>(redirectUris));
+ configureDefaultClientGrantsAndScopes(ipPassClient);
+ ipPassClient.setClientIpAddress("127.0.0.1");
+ this.setClient(ipPassClient);
+
+ Client ipFailClient = createPublicClients ? new
Client("consumer-id-ip-fail", null, false)
+ : new Client("consumer-id-ip-fail", "this-is-a-secret", true);
+ ipFailClient.setRedirectUris(new ArrayList<>(redirectUris));
+ configureDefaultClientGrantsAndScopes(ipFailClient);
+ ipFailClient.setClientIpAddress("203.0.113.10");
+ this.setClient(ipFailClient);
+ }
+
@Override
protected ServerAccessToken createNewAccessToken(Client client,
UserSubject userSub) {
ServerAccessToken token = super.createNewAccessToken(client, userSub);
diff --git
a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/filters/OAuth2JwtFiltersTest.java
b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/filters/OAuth2JwtFiltersTest.java
index 9c2a26a1a69..70e9b2bd600 100644
---
a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/filters/OAuth2JwtFiltersTest.java
+++
b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/filters/OAuth2JwtFiltersTest.java
@@ -24,6 +24,7 @@ import java.util.Collections;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status.Family;
import org.apache.cxf.bus.spring.SpringBusFactory;
import org.apache.cxf.helpers.JavaUtils;
import org.apache.cxf.jaxrs.client.WebClient;
@@ -99,14 +100,65 @@ public class OAuth2JwtFiltersTest extends
AbstractBusClientServerTestBase {
doTestServiceWithJwtTokenAndScope(oauthServiceAddress, rsAddress);
}
+ @org.junit.Test
+ public void testServiceWithJwtTokenAndClientIpMatch() throws Exception {
+ String oauthServiceAddress = "https://localhost:" + OAUTH_PORT +
"/services/";
+ String rsAddress = "https://127.0.0.1:" + PORT +
"/secured/bookstore/books";
+ doTestServiceWithJwtTokenAndScope(oauthServiceAddress, rsAddress,
"consumer-id-ip-pass");
+ }
+
+ @org.junit.Test
+ public void testServiceWithJwtTokenAndClientIpMismatch() throws Exception {
+ String oauthServiceAddress = "https://localhost:" + OAUTH_PORT +
"/services/";
+ String rsAddress = "https://127.0.0.1:" + PORT +
"/secured/bookstore/books";
+
+ final AuthorizationMetadata authorizationMetadata =
+ OAuthClientUtils.getAuthorizationMetadata(oauthServiceAddress);
+ final String scope = "create_book";
+ final String clientId = "consumer-id-ip-fail";
+
+ final URI authorizationURI = OAuthClientUtils.getAuthorizationURI(
+ authorizationMetadata.getAuthorizationEndpoint().toString(),
+ clientId, null, null, scope);
+
+ WebClient oauthClient = WebClient.create(authorizationURI.toString(),
OAuth2TestUtils.setupProviders(),
+ "alice", "security", null);
+ WebClient.getConfig(oauthClient).getRequestContext().put(
+ org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+ final String location = OAuth2TestUtils.getLocation(oauthClient,
+
oauthClient.accept(MediaType.APPLICATION_JSON).get(OAuthAuthorizationData.class),
+ null);
+ final String code = OAuth2TestUtils.getSubstring(location, "code");
+ assertNotNull(code);
+
+ final ClientAccessToken accessToken = OAuthClientUtils.getAccessToken(
+ authorizationMetadata.getTokenEndpoint().toString(),
+ new Consumer(clientId, "this-is-a-secret"),
+ new AuthorizationCodeGrant(code),
+ true);
+ assertNotNull(accessToken.getTokenKey());
+
+ WebClient client = WebClient.create(rsAddress,
OAuth2TestUtils.setupProviders())
+ .authorization(new ClientAccessToken(BEARER_AUTHORIZATION_SCHEME,
accessToken.getTokenKey()));
+ Response response = client.type("application/xml").post(new
Book("book", 123L));
+ assertEquals(Family.CLIENT_ERROR,
response.getStatusInfo().getFamily());
+ }
+
private void doTestServiceWithJwtTokenAndScope(String oauthService, String
rsAddress) throws Exception {
+ doTestServiceWithJwtTokenAndScope(oauthService, rsAddress,
"consumer-id");
+ }
+
+ private void doTestServiceWithJwtTokenAndScope(String oauthService,
+ String rsAddress,
+ String clientId) throws
Exception {
final AuthorizationMetadata authorizationMetadata =
OAuthClientUtils.getAuthorizationMetadata(oauthService);
final String scope = "create_book";
final URI authorizationURI = OAuthClientUtils.getAuthorizationURI(
authorizationMetadata.getAuthorizationEndpoint().toString(),
- "consumer-id", null, null, scope);
+ clientId, null, null, scope);
// Get Authorization Code
WebClient oauthClient = WebClient.create(authorizationURI.toString(),
OAuth2TestUtils.setupProviders(),
@@ -124,7 +176,7 @@ public class OAuth2JwtFiltersTest extends
AbstractBusClientServerTestBase {
// Now get the access token
final ClientAccessToken accessToken = OAuthClientUtils.getAccessToken(
authorizationMetadata.getTokenEndpoint().toString(),
- new Consumer("consumer-id", "this-is-a-secret"),
+ new Consumer(clientId, "this-is-a-secret"),
new AuthorizationCodeGrant(code),
true);
assertNotNull(accessToken.getTokenKey());
@@ -136,7 +188,7 @@ public class OAuth2JwtFiltersTest extends
AbstractBusClientServerTestBase {
: "org/apache/cxf/systest/jaxrs/security/alice.rs.properties",
null);
assertTrue(jwtConsumer.verifySignatureWith(verifier));
JwtClaims claims = jwtConsumer.getJwtClaims();
- assertEquals("consumer-id",
claims.getStringProperty(OAuthConstants.CLIENT_ID));
+ assertEquals(clientId,
claims.getStringProperty(OAuthConstants.CLIENT_ID));
assertEquals("alice", claims.getStringProperty("username"));
assertTrue(claims.getStringProperty(OAuthConstants.SCOPE).contains(scope));
// Now invoke on the service with the access token