This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git
The following commit(s) were added to refs/heads/master by this push:
new a9a7302 Make sure that only the client associated with a token can
revoke it
a9a7302 is described below
commit a9a7302896c4d52bace3af0ac2e252bf6e4d6ba1
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Tue Nov 5 16:20:07 2019 +0000
Make sure that only the client associated with a token can revoke it
---
.../oauth2/provider/AbstractOAuthDataProvider.java | 37 +++++++------
.../oauth2/grants/RevocationServiceTest.java | 60 ++++++++++++++++++++++
2 files changed, 82 insertions(+), 15 deletions(-)
diff --git
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
index 3413976..3681b86 100644
---
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
+++
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
@@ -199,18 +199,18 @@ public abstract class AbstractOAuthDataProvider
implements OAuthDataProvider, Cl
public ServerAccessToken refreshAccessToken(Client client, String
refreshTokenKey,
List<String> restrictedScopes)
throws OAuthServiceException {
RefreshToken currentRefreshToken = recycleRefreshTokens
- ? revokeRefreshToken(refreshTokenKey) :
getRefreshToken(refreshTokenKey);
+ ? revokeRefreshToken(client, refreshTokenKey) :
getRefreshToken(refreshTokenKey);
if (currentRefreshToken == null) {
throw new OAuthServiceException(OAuthConstants.ACCESS_DENIED);
}
if (OAuthUtils.isExpired(currentRefreshToken.getIssuedAt(),
currentRefreshToken.getExpiresIn())) {
if (!recycleRefreshTokens) {
- revokeRefreshToken(refreshTokenKey);
+ revokeRefreshToken(client, refreshTokenKey);
}
throw new OAuthServiceException(OAuthConstants.ACCESS_DENIED);
}
if (recycleRefreshTokens) {
- revokeAccessTokens(currentRefreshToken);
+ revokeAccessTokens(client, currentRefreshToken);
}
ServerAccessToken at = doRefreshAccessToken(client,
currentRefreshToken, restrictedScopes);
@@ -227,16 +227,17 @@ public abstract class AbstractOAuthDataProvider
implements OAuthDataProvider, Cl
public void revokeToken(Client client, String tokenKey, String
tokenTypeHint) throws OAuthServiceException {
ServerAccessToken accessToken = null;
if (!OAuthConstants.REFRESH_TOKEN.equals(tokenTypeHint)) {
- accessToken = revokeAccessToken(tokenKey);
+ accessToken = revokeAccessToken(client, tokenKey);
}
if (accessToken != null) {
- handleLinkedRefreshToken(accessToken);
+ handleLinkedRefreshToken(client, accessToken);
} else if (!OAuthConstants.ACCESS_TOKEN.equals(tokenTypeHint)) {
- RefreshToken currentRefreshToken = revokeRefreshToken(tokenKey);
- revokeAccessTokens(currentRefreshToken);
+ RefreshToken currentRefreshToken = revokeRefreshToken(client,
tokenKey);
+ revokeAccessTokens(client, currentRefreshToken);
}
}
- protected void handleLinkedRefreshToken(ServerAccessToken accessToken) {
+
+ protected void handleLinkedRefreshToken(Client client, ServerAccessToken
accessToken) {
if (accessToken != null && accessToken.getRefreshToken() != null) {
RefreshToken rt = getRefreshToken(accessToken.getRefreshToken());
if (rt == null) {
@@ -245,7 +246,7 @@ public abstract class AbstractOAuthDataProvider implements
OAuthDataProvider, Cl
unlinkRefreshAccessToken(rt, accessToken.getTokenKey());
if (rt.getAccessTokens().isEmpty()) {
- revokeRefreshToken(rt.getTokenKey());
+ revokeRefreshToken(client, rt.getTokenKey());
} else {
saveRefreshToken(rt);
}
@@ -253,10 +254,10 @@ public abstract class AbstractOAuthDataProvider
implements OAuthDataProvider, Cl
}
- protected void revokeAccessTokens(RefreshToken currentRefreshToken) {
+ protected void revokeAccessTokens(Client client, RefreshToken
currentRefreshToken) {
if (currentRefreshToken != null) {
for (String accessTokenKey :
currentRefreshToken.getAccessTokens()) {
- revokeAccessToken(accessTokenKey);
+ revokeAccessToken(client, accessTokenKey);
}
}
}
@@ -495,13 +496,13 @@ public abstract class AbstractOAuthDataProvider
implements OAuthDataProvider, Cl
List<RefreshToken> refreshTokens = getRefreshTokens(c, null);
if (refreshTokens != null) {
for (RefreshToken rt : refreshTokens) {
- revokeRefreshToken(rt.getTokenKey());
+ revokeRefreshToken(c, rt.getTokenKey());
}
}
List<ServerAccessToken> accessTokens = getAccessTokens(c, null);
if (accessTokens != null) {
for (ServerAccessToken at : accessTokens) {
- revokeAccessToken(at.getTokenKey());
+ revokeAccessToken(c, at.getTokenKey());
}
}
}
@@ -549,16 +550,22 @@ public abstract class AbstractOAuthDataProvider
implements OAuthDataProvider, Cl
return null;
}
- protected ServerAccessToken revokeAccessToken(String accessTokenKey) {
+ protected ServerAccessToken revokeAccessToken(Client client, String
accessTokenKey) {
ServerAccessToken at = getAccessToken(accessTokenKey);
if (at != null) {
+ if (!at.getClient().getClientId().equals(client.getClientId())) {
+ throw new OAuthServiceException(OAuthConstants.INVALID_GRANT);
+ }
doRevokeAccessToken(at);
}
return at;
}
- protected RefreshToken revokeRefreshToken(String refreshTokenKey) {
+ protected RefreshToken revokeRefreshToken(Client client, String
refreshTokenKey) {
RefreshToken refreshToken = getRefreshToken(refreshTokenKey);
if (refreshToken != null) {
+ if
(!refreshToken.getClient().getClientId().equals(client.getClientId())) {
+ throw new OAuthServiceException(OAuthConstants.INVALID_GRANT);
+ }
doRevokeRefreshToken(refreshToken);
}
return refreshToken;
diff --git
a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/RevocationServiceTest.java
b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/RevocationServiceTest.java
index 057eda6..7847f7a 100644
---
a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/RevocationServiceTest.java
+++
b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/RevocationServiceTest.java
@@ -201,6 +201,66 @@ public class RevocationServiceTest extends
AbstractBusClientServerTestBase {
assertEquals(400, response.getStatus());
}
+ @org.junit.Test
+ public void testAccessTokenRevocationWrongClient() throws Exception {
+ URL busFile = RevocationServiceTest.class.getResource("client.xml");
+
+ String address = "https://localhost:" + port + "/services/";
+ WebClient client = WebClient.create(address,
OAuth2TestUtils.setupProviders(),
+ "alice", "security",
busFile.toString());
+ // Save the Cookie for the second request...
+ WebClient.getConfig(client).getRequestContext().put(
+ org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+ // Get Authorization Code
+ String code = OAuth2TestUtils.getAuthorizationCode(client);
+ assertNotNull(code);
+
+ // Now get the access token
+ client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+ "consumer-id", "this-is-a-secret",
busFile.toString());
+ // Save the Cookie for the second request...
+ WebClient.getConfig(client).getRequestContext().put(
+ org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+ ClientAccessToken accessToken =
OAuth2TestUtils.getAccessTokenWithAuthorizationCode(client, code);
+ assertNotNull(accessToken.getTokenKey());
+
+ // Now query the token introspection service to make sure the token is
valid
+ client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+ "consumer-id", "this-is-a-secret",
busFile.toString());
+
client.accept("application/json").type("application/x-www-form-urlencoded");
+ Form form = new Form();
+ form.param("token", accessToken.getTokenKey());
+ client.path("introspect/");
+ Response response = client.post(form);
+
+ TokenIntrospection tokenIntrospection =
response.readEntity(TokenIntrospection.class);
+ assertTrue(tokenIntrospection.isActive());
+
+ // Now try to revoke the token as a different client (this should
fail, but no exception is thrown)
+ client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+ "consumer-id-aud", "this-is-a-secret",
busFile.toString());
+
client.accept("application/json").type("application/x-www-form-urlencoded");
+ form = new Form();
+ form.param("token", accessToken.getTokenKey());
+ client.path("revoke/");
+ response = client.post(form);
+
+ // Now check the token introspection service again to make sure the
token is still valid
+ // (the token revocation call failed)
+ client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+ "consumer-id", "this-is-a-secret",
busFile.toString());
+
client.accept("application/json").type("application/x-www-form-urlencoded");
+ form = new Form();
+ form.param("token", accessToken.getTokenKey());
+ client.path("introspect/");
+ response = client.post(form);
+
+ tokenIntrospection = response.readEntity(TokenIntrospection.class);
+ assertTrue(tokenIntrospection.isActive());
+ }
+
//
// Server implementations
//