keycloak-uncached
Changes
services/src/main/java/org/keycloak/services/clientregistration/AdapterInstallationClientRegistrationProvider.java 41(+5 -36)
services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationAuth.java 133(+88 -45)
services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationTokenUtils.java 15(+7 -8)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AdapterInstallationConfigTest.java 8(+4 -4)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/ClientRegistrationTest.java 18(+14 -4)
Details
diff --git a/services/src/main/java/org/keycloak/services/clientregistration/AdapterInstallationClientRegistrationProvider.java b/services/src/main/java/org/keycloak/services/clientregistration/AdapterInstallationClientRegistrationProvider.java
index 65a4339..86a71e3 100644
--- a/services/src/main/java/org/keycloak/services/clientregistration/AdapterInstallationClientRegistrationProvider.java
+++ b/services/src/main/java/org/keycloak/services/clientregistration/AdapterInstallationClientRegistrationProvider.java
@@ -17,18 +17,17 @@
package org.keycloak.services.clientregistration;
-import org.keycloak.authentication.AuthenticationProcessor;
-import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
-import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil;
-import org.keycloak.services.ForbiddenException;
import org.keycloak.services.managers.ClientManager;
import org.keycloak.services.managers.RealmManager;
-import javax.ws.rs.*;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -52,12 +51,7 @@ public class AdapterInstallationClientRegistrationProvider implements ClientRegi
event.event(EventType.CLIENT_INFO);
ClientModel client = session.getContext().getRealm().getClientByClientId(clientId);
-
- if (auth.isAuthenticated()) {
- auth.requireView(client);
- } else {
- authenticateClient(client);
- }
+ auth.requireView(client);
ClientManager clientManager = new ClientManager(new RealmManager(session));
Object rep = clientManager.toInstallationRepresentation(session.getContext().getRealm(), client, session.getContext().getAuthServerUrl());
@@ -80,29 +74,4 @@ public class AdapterInstallationClientRegistrationProvider implements ClientRegi
public void close() {
}
- private void authenticateClient(ClientModel client) {
- if (client.isPublicClient()) {
- return;
- }
-
- AuthenticationProcessor processor = AuthorizeClientUtil.getAuthenticationProcessor(session, event);
-
- Response response = processor.authenticateClient();
- if (response != null) {
- event.client(client.getClientId()).error(Errors.NOT_ALLOWED);
- throw new ForbiddenException();
- }
-
- ClientModel authClient = processor.getClient();
- if (client == null) {
- event.client(client.getClientId()).error(Errors.NOT_ALLOWED);
- throw new ForbiddenException();
- }
-
- if (!authClient.getClientId().equals(client.getClientId())) {
- event.client(client.getClientId()).error(Errors.NOT_ALLOWED);
- throw new ForbiddenException();
- }
- }
-
}
diff --git a/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationAuth.java b/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationAuth.java
index 5dc7285..5564ef2 100644
--- a/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationAuth.java
+++ b/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationAuth.java
@@ -17,20 +17,28 @@
package org.keycloak.services.clientregistration;
-import com.sun.xml.bind.v2.runtime.reflect.opt.Const;
+import org.jboss.resteasy.spi.Failure;
+import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.UnauthorizedException;
import org.keycloak.Config;
+import org.keycloak.authentication.AuthenticationProcessor;
import org.keycloak.common.util.Time;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
-import org.keycloak.models.*;
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ClientInitialAccessModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil;
import org.keycloak.representations.JsonWebToken;
import org.keycloak.services.ForbiddenException;
import org.keycloak.util.TokenUtil;
import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -49,8 +57,6 @@ public class ClientRegistrationAuth {
public ClientRegistrationAuth(KeycloakSession session, EventBuilder event) {
this.session = session;
this.event = event;
-
- init();
}
private void init() {
@@ -67,41 +73,39 @@ public class ClientRegistrationAuth {
return;
}
- jwt = ClientRegistrationTokenUtils.parseToken(realm, uri, split[1]);
+ jwt = ClientRegistrationTokenUtils.verifyToken(realm, uri, split[1]);
+ if (jwt == null) {
+ throw unauthorized();
+ }
if (isInitialAccessToken()) {
initialAccessModel = session.sessions().getClientInitialAccessModel(session.getContext().getRealm(), jwt.getId());
if (initialAccessModel == null) {
- throw new ForbiddenException();
+ throw unauthorized();
}
}
}
- public boolean isAuthenticated() {
- return jwt != null;
- }
-
- public boolean isBearerToken() {
- return TokenUtil.TOKEN_TYPE_BEARER.equals(jwt.getType());
+ private boolean isBearerToken() {
+ return jwt != null && TokenUtil.TOKEN_TYPE_BEARER.equals(jwt.getType());
}
public boolean isInitialAccessToken() {
- return ClientRegistrationTokenUtils.TYPE_INITIAL_ACCESS_TOKEN.equals(jwt.getType());
+ return jwt != null && ClientRegistrationTokenUtils.TYPE_INITIAL_ACCESS_TOKEN.equals(jwt.getType());
}
public boolean isRegistrationAccessToken() {
- return ClientRegistrationTokenUtils.TYPE_REGISTRATION_ACCESS_TOKEN.equals(jwt.getType());
+ return jwt != null && ClientRegistrationTokenUtils.TYPE_REGISTRATION_ACCESS_TOKEN.equals(jwt.getType());
}
public void requireCreate() {
- if (!isAuthenticated()) {
- event.error(Errors.NOT_ALLOWED);
- throw new UnauthorizedException();
- }
+ init();
if (isBearerToken()) {
if (hasRole(AdminRoles.MANAGE_CLIENTS, AdminRoles.CREATE_CLIENT)) {
return;
+ } else {
+ throw forbidden();
}
} else if (isInitialAccessToken()) {
if (initialAccessModel.getRemainingCount() > 0) {
@@ -111,58 +115,55 @@ public class ClientRegistrationAuth {
}
}
- event.error(Errors.NOT_ALLOWED);
- throw new ForbiddenException();
+ throw unauthorized();
}
public void requireView(ClientModel client) {
- if (!isAuthenticated()) {
- event.error(Errors.NOT_ALLOWED);
- throw new UnauthorizedException();
- }
-
- if (client == null) {
- event.error(Errors.NOT_ALLOWED);
- throw new ForbiddenException();
- }
+ init();
if (isBearerToken()) {
if (hasRole(AdminRoles.MANAGE_CLIENTS, AdminRoles.VIEW_CLIENTS)) {
+ if (client == null) {
+ throw notFound();
+ }
return;
+ } else {
+ throw forbidden();
}
} else if (isRegistrationAccessToken()) {
- if (client.getRegistrationToken() != null && client.getRegistrationToken().equals(jwt.getId())) {
+ if (client.getRegistrationToken() != null && client != null && client.getRegistrationToken().equals(jwt.getId())) {
+ return;
+ }
+ } else if (isInitialAccessToken()) {
+ throw unauthorized();
+ } else {
+ if (authenticateClient(client)) {
return;
}
}
- event.error(Errors.NOT_ALLOWED);
- throw new ForbiddenException();
+ throw unauthorized();
}
public void requireUpdate(ClientModel client) {
- if (!isAuthenticated()) {
- event.error(Errors.NOT_ALLOWED);
- throw new UnauthorizedException();
- }
-
- if (client == null) {
- event.error(Errors.NOT_ALLOWED);
- throw new ForbiddenException();
- }
+ init();
if (isBearerToken()) {
if (hasRole(AdminRoles.MANAGE_CLIENTS)) {
+ if (client == null) {
+ throw notFound();
+ }
return;
+ } else {
+ throw forbidden();
}
} else if (isRegistrationAccessToken()) {
- if (client.getRegistrationToken() != null && client.getRegistrationToken().equals(jwt.getId())) {
+ if (client.getRegistrationToken() != null && client != null && client.getRegistrationToken().equals(jwt.getId())) {
return;
}
}
- event.error(Errors.NOT_ALLOWED);
- throw new ForbiddenException();
+ throw unauthorized();
}
public ClientInitialAccessModel getInitialAccessModel() {
@@ -207,4 +208,46 @@ public class ClientRegistrationAuth {
}
}
+ private boolean authenticateClient(ClientModel client) {
+ if (client.isPublicClient()) {
+ return true;
+ }
+
+ AuthenticationProcessor processor = AuthorizeClientUtil.getAuthenticationProcessor(session, event);
+
+ Response response = processor.authenticateClient();
+ if (response != null) {
+ event.client(client.getClientId()).error(Errors.NOT_ALLOWED);
+ throw unauthorized();
+ }
+
+ ClientModel authClient = processor.getClient();
+ if (client == null) {
+ event.client(client.getClientId()).error(Errors.NOT_ALLOWED);
+ throw unauthorized();
+ }
+
+ if (!authClient.getClientId().equals(client.getClientId())) {
+ event.client(client.getClientId()).error(Errors.NOT_ALLOWED);
+ throw unauthorized();
+ }
+
+ return true;
+ }
+
+ private Failure unauthorized() {
+ event.error(Errors.NOT_ALLOWED);
+ return new UnauthorizedException();
+ }
+
+ private Failure forbidden() {
+ event.error(Errors.NOT_ALLOWED);
+ return new ForbiddenException();
+ }
+
+ private Failure notFound() {
+ event.error(Errors.NOT_ALLOWED);
+ return new NotFoundException("Client not found");
+ }
+
}
diff --git a/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationTokenUtils.java b/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationTokenUtils.java
index 2cd74ba..2fe65cc 100755
--- a/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationTokenUtils.java
+++ b/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationTokenUtils.java
@@ -28,7 +28,6 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.JsonWebToken;
-import org.keycloak.services.ForbiddenException;
import org.keycloak.services.Urls;
import org.keycloak.util.TokenUtil;
@@ -57,37 +56,37 @@ public class ClientRegistrationTokenUtils {
return createToken(realm, uri, model.getId(), TYPE_INITIAL_ACCESS_TOKEN, model.getExpiration() > 0 ? model.getTimestamp() + model.getExpiration() : 0);
}
- public static JsonWebToken parseToken(RealmModel realm, UriInfo uri, String token) {
+ public static JsonWebToken verifyToken(RealmModel realm, UriInfo uri, String token) {
JWSInput input;
try {
input = new JWSInput(token);
} catch (JWSInputException e) {
- throw new ForbiddenException(e);
+ return null;
}
if (!RSAProvider.verify(input, realm.getPublicKey())) {
- throw new ForbiddenException("Invalid signature");
+ return null;
}
JsonWebToken jwt;
try {
jwt = input.readJsonContent(JsonWebToken.class);
} catch (JWSInputException e) {
- throw new ForbiddenException(e);
+ return null;
}
if (!getIssuer(realm, uri).equals(jwt.getIssuer())) {
- throw new ForbiddenException("Issuer doesn't match");
+ return null;
}
if (!jwt.isActive()) {
- throw new ForbiddenException("Expired token");
+ return null;
}
if (!(TokenUtil.TOKEN_TYPE_BEARER.equals(jwt.getType()) ||
TYPE_INITIAL_ACCESS_TOKEN.equals(jwt.getType()) ||
TYPE_REGISTRATION_ACCESS_TOKEN.equals(jwt.getType()))) {
- throw new ForbiddenException("Invalid token type");
+ return null;
}
return jwt;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AdapterInstallationConfigTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AdapterInstallationConfigTest.java
index 4272025..0a4fe4b 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AdapterInstallationConfigTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AdapterInstallationConfigTest.java
@@ -103,9 +103,9 @@ public class AdapterInstallationConfigTest extends AbstractClientRegistrationTes
try {
reg.getAdapterConfig(client.getClientId());
- fail("Expected 403");
+ fail("Expected 401");
} catch (ClientRegistrationException e) {
- assertEquals(403, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
+ assertEquals(401, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
}
}
@@ -115,9 +115,9 @@ public class AdapterInstallationConfigTest extends AbstractClientRegistrationTes
try {
reg.getAdapterConfig(client2.getClientId());
- fail("Expected 403");
+ fail("Expected 401");
} catch (ClientRegistrationException e) {
- assertEquals(403, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
+ assertEquals(401, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
}
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/ClientRegistrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/ClientRegistrationTest.java
index 70bfed0..0ef5e26 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/ClientRegistrationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/ClientRegistrationTest.java
@@ -126,8 +126,14 @@ public class ClientRegistrationTest extends AbstractClientRegistrationTest {
@Test
public void getClientNotFound() throws ClientRegistrationException {
authManageClients();
+ assertNull(reg.get("invalid"));
+ }
+
+ @Test
+ public void getClientNotFoundNoAccess() throws ClientRegistrationException {
+ authNoAccess();
try {
- reg.get(CLIENT_ID);
+ reg.get("invalid");
fail("Expected 403");
} catch (ClientRegistrationException e) {
assertEquals(403, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
@@ -181,10 +187,14 @@ public class ClientRegistrationTest extends AbstractClientRegistrationTest {
public void updateClientNotFound() throws ClientRegistrationException {
authManageClients();
try {
- updateClient();
- fail("Expected 403");
+ ClientRepresentation client = new ClientRepresentation();
+ client.setClientId("invalid");
+
+ reg.update(client);
+
+ fail("Expected 404");
} catch (ClientRegistrationException e) {
- assertEquals(403, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
+ assertEquals(404, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
}
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/InitialAccessTokenTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/InitialAccessTokenTest.java
index 4f4d204..ad33f52 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/InitialAccessTokenTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/InitialAccessTokenTest.java
@@ -58,7 +58,7 @@ public class InitialAccessTokenTest extends AbstractClientRegistrationTest {
try {
reg.create(rep);
} catch (ClientRegistrationException e) {
- Assert.assertEquals(403, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
+ Assert.assertEquals(401, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
}
}
@@ -79,7 +79,7 @@ public class InitialAccessTokenTest extends AbstractClientRegistrationTest {
try {
reg.create(rep);
} catch (ClientRegistrationException e) {
- Assert.assertEquals(403, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
+ Assert.assertEquals(401, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
}
}
@@ -113,7 +113,7 @@ public class InitialAccessTokenTest extends AbstractClientRegistrationTest {
try {
reg.create(rep);
} catch (ClientRegistrationException e) {
- Assert.assertEquals(403, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
+ Assert.assertEquals(401, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
}
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/RegistrationAccessTokenTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/RegistrationAccessTokenTest.java
index c6fb960..96a0010 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/RegistrationAccessTokenTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/RegistrationAccessTokenTest.java
@@ -59,8 +59,8 @@ public class RegistrationAccessTokenTest extends AbstractClientRegistrationTest
try {
reg.get(client.getClientId());
fail("Expected 403");
- } catch (ClientRegistrationException e) {
- assertEquals(403, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
+ } catch (Exception e) {
+ assertEquals(401, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
}
}
return null;
@@ -82,9 +82,9 @@ public class RegistrationAccessTokenTest extends AbstractClientRegistrationTest
reg.auth(Auth.token("invalid"));
try {
reg.get(client.getClientId());
- fail("Expected 403");
+ fail("Expected 401");
} catch (ClientRegistrationException e) {
- assertEquals(403, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
+ assertEquals(401, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
}
}
@@ -109,9 +109,9 @@ public class RegistrationAccessTokenTest extends AbstractClientRegistrationTest
reg.auth(Auth.token("invalid"));
try {
reg.update(client);
- fail("Expected 403");
+ fail("Expected 401");
} catch (ClientRegistrationException e) {
- assertEquals(403, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
+ assertEquals(401, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
}
assertEquals("http://root", getClient(client.getId()).getRootUrl());
@@ -128,9 +128,9 @@ public class RegistrationAccessTokenTest extends AbstractClientRegistrationTest
reg.auth(Auth.token("invalid"));
try {
reg.delete(client);
- fail("Expected 403");
+ fail("Expected 401");
} catch (ClientRegistrationException e) {
- assertEquals(403, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
+ assertEquals(401, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
}
assertNotNull(getClient(client.getId()));
}