Merge pull request #998 from pedroigor/master

[KEYCLOAK-883] - Minor changes to the configuration of identity providers for clients.
This commit is contained in:
Pedro Igor 2015-02-25 21:02:43 -03:00
commit bccffadc7c
12 changed files with 120 additions and 41 deletions

View file

@ -22,7 +22,9 @@
package org.keycloak.login.freemarker.model; package org.keycloak.login.freemarker.model;
import org.keycloak.OAuth2Constants; import org.keycloak.OAuth2Constants;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.Constants;
import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.services.resources.flows.Urls; import org.keycloak.services.resources.flows.Urls;
@ -57,12 +59,19 @@ public class IdentityProviderBean {
ClientModel clientModel = realm.findClient(clientId); ClientModel clientModel = realm.findClient(clientId);
if (clientModel != null && !clientModel.hasIdentityProvider(identityProvider.getId())) { if (clientModel != null && !clientModel.hasIdentityProvider(identityProvider.getId())) {
if (ApplicationModel.class.isInstance(clientModel)) {
ApplicationModel applicationModel = (ApplicationModel) clientModel;
if (applicationModel.getName().equals(Constants.ACCOUNT_MANAGEMENT_APP)) {
addIdentityProvider(realm, baseURI, identityProvider);
}
}
continue; continue;
} }
} }
String loginUrl = Urls.identityProviderAuthnRequest(baseURI, identityProvider.getId(), realm.getName()).toString(); addIdentityProvider(realm, baseURI, identityProvider);
providers.add(new IdentityProvider(identityProvider.getId(), identityProvider.getName(), loginUrl));
} }
} }
@ -72,6 +81,11 @@ public class IdentityProviderBean {
} }
} }
private void addIdentityProvider(RealmModel realm, URI baseURI, IdentityProviderModel identityProvider) {
String loginUrl = Urls.identityProviderAuthnRequest(baseURI, identityProvider.getId(), realm.getName()).toString();
providers.add(new IdentityProvider(identityProvider.getId(), identityProvider.getName(), loginUrl));
}
public List<IdentityProvider> getProviders() { public List<IdentityProvider> getProviders() {
return providers; return providers;
} }

View file

@ -473,6 +473,17 @@ public class RepresentationToModel {
applicationModel.setProtocolMappers(ids); applicationModel.setProtocolMappers(ids);
} }
List<String> allowedIdentityProviders = resourceRep.getAllowedIdentityProviders();
if (allowedIdentityProviders == null || allowedIdentityProviders.isEmpty()) {
allowedIdentityProviders = new ArrayList<String>();
for (IdentityProviderModel identityProvider : realm.getIdentityProviders()) {
allowedIdentityProviders.add(identityProvider.getId());
}
}
applicationModel.updateAllowedIdentityProviders(allowedIdentityProviders);
return applicationModel; return applicationModel;
} }
@ -601,6 +612,19 @@ public class RepresentationToModel {
public static OAuthClientModel createOAuthClient(OAuthClientRepresentation rep, RealmModel realm) { public static OAuthClientModel createOAuthClient(OAuthClientRepresentation rep, RealmModel realm) {
OAuthClientModel model = createOAuthClient(rep.getId(), rep.getName(), realm); OAuthClientModel model = createOAuthClient(rep.getId(), rep.getName(), realm);
List<String> allowedIdentityProviders = rep.getAllowedIdentityProviders();
if (allowedIdentityProviders == null || allowedIdentityProviders.isEmpty()) {
allowedIdentityProviders = new ArrayList<String>();
for (IdentityProviderModel identityProvider : realm.getIdentityProviders()) {
allowedIdentityProviders.add(identityProvider.getId());
}
}
model.updateAllowedIdentityProviders(allowedIdentityProviders);
updateOAuthClient(rep, model); updateOAuthClient(rep, model);
return model; return model;
} }

View file

@ -130,10 +130,6 @@ public class CachedClient {
} }
public boolean hasIdentityProvider(String providerId) { public boolean hasIdentityProvider(String providerId) {
if (this.allowedIdentityProviders.isEmpty()) {
return true;
}
return this.allowedIdentityProviders.contains(providerId); return this.allowedIdentityProviders.contains(providerId);
} }

View file

@ -343,11 +343,6 @@ public abstract class ClientAdapter implements ClientModel {
@Override @Override
public boolean hasIdentityProvider(String providerId) { public boolean hasIdentityProvider(String providerId) {
List<String> allowedIdentityProviders = getAllowedIdentityProviders(); List<String> allowedIdentityProviders = getAllowedIdentityProviders();
if (allowedIdentityProviders.isEmpty()) {
return true;
}
return allowedIdentityProviders.contains(providerId); return allowedIdentityProviders.contains(providerId);
} }

View file

@ -341,11 +341,6 @@ public abstract class ClientAdapter<T extends MongoIdentifiableEntity> extends A
@Override @Override
public boolean hasIdentityProvider(String providerId) { public boolean hasIdentityProvider(String providerId) {
List<String> allowedIdentityProviders = getMongoEntityAsClient().getAllowedIdentityProviders(); List<String> allowedIdentityProviders = getMongoEntityAsClient().getAllowedIdentityProviders();
if (allowedIdentityProviders.isEmpty()) {
return true;
}
return allowedIdentityProviders.contains(providerId); return allowedIdentityProviders.contains(providerId);
} }
} }

View file

@ -391,7 +391,6 @@ public class IdentityBrokerService {
ClientSessionCode clientCode = ClientSessionCode.parse(code, this.session, this.realmModel); ClientSessionCode clientCode = ClientSessionCode.parse(code, this.session, this.realmModel);
if (clientCode != null && clientCode.isValid(AUTHENTICATE)) { if (clientCode != null && clientCode.isValid(AUTHENTICATE)) {
validateClientPermissions(clientCode, providerId);
ClientSessionModel clientSession = clientCode.getClientSession(); ClientSessionModel clientSession = clientCode.getClientSession();
if (clientSession != null) { if (clientSession != null) {
@ -405,6 +404,8 @@ public class IdentityBrokerService {
if (clientSession.getUserSession() != null) { if (clientSession.getUserSession() != null) {
this.event.session(clientSession.getUserSession()); this.event.session(clientSession.getUserSession());
} }
} else {
validateClientPermissions(clientCode, providerId);
} }
if (isDebugEnabled()) { if (isDebugEnabled()) {

View file

@ -1,6 +1,7 @@
package org.keycloak.services.resources.admin; package org.keycloak.services.resources.admin;
import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.annotations.cache.NoCache;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.ModelDuplicateException;
@ -16,6 +17,7 @@ import javax.ws.rs.GET;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.util.List;
/** /**
* @author Pedro Igor * @author Pedro Igor
@ -42,6 +44,8 @@ public class IdentityProviderResource {
@DELETE @DELETE
@NoCache @NoCache
public Response delete() { public Response delete() {
removeClientIdentityProviders(this.realm.getApplications(), this.identityProviderModel);
removeClientIdentityProviders(this.realm.getApplications(), this.identityProviderModel);
this.realm.removeIdentityProviderById(this.identityProviderModel.getId()); this.realm.removeIdentityProviderById(this.identityProviderModel.getId());
return Response.noContent().build(); return Response.noContent().build();
} }
@ -56,4 +60,15 @@ public class IdentityProviderResource {
return Flows.errors().exists("Identity Provider " + model.getId() + " already exists"); return Flows.errors().exists("Identity Provider " + model.getId() + " already exists");
} }
} }
private void removeClientIdentityProviders(List<? extends ClientModel> clients, IdentityProviderModel identityProvider) {
for (ClientModel clientModel : clients) {
List<String> allowedIdentityProviders = clientModel.getAllowedIdentityProviders();
allowedIdentityProviders.remove(identityProvider.getId());
clientModel.updateAllowedIdentityProviders(allowedIdentityProviders);
}
}
} }

View file

@ -7,6 +7,7 @@ import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.broker.provider.IdentityProvider; import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.broker.provider.IdentityProviderFactory; import org.keycloak.broker.provider.IdentityProviderFactory;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.ModelDuplicateException;
@ -89,6 +90,10 @@ public class IdentityProvidersResource {
try { try {
this.realm.addIdentityProvider(RepresentationToModel.toModel(representation)); this.realm.addIdentityProvider(RepresentationToModel.toModel(representation));
updateClientIdentityProviders(this.realm.getApplications(), representation);
updateClientIdentityProviders(this.realm.getOAuthClients(), representation);
return Response.created(uriInfo.getAbsolutePathBuilder().path(representation.getProviderId()).build()).build(); return Response.created(uriInfo.getAbsolutePathBuilder().path(representation.getProviderId()).build()).build();
} catch (ModelDuplicateException e) { } catch (ModelDuplicateException e) {
return Flows.errors().exists("Identity Provider " + representation.getId() + " already exists"); return Flows.errors().exists("Identity Provider " + representation.getId() + " already exists");
@ -171,4 +176,14 @@ public class IdentityProvidersResource {
return allProviders; return allProviders;
} }
private void updateClientIdentityProviders(List<? extends ClientModel> clients, IdentityProviderRepresentation identityProvider) {
for (ClientModel clientModel : clients) {
List<String> allowedIdentityProviders = clientModel.getAllowedIdentityProviders();
allowedIdentityProviders.add(identityProvider.getId());
clientModel.updateAllowedIdentityProviders(allowedIdentityProviders);
}
}
} }

View file

@ -24,6 +24,7 @@ import org.junit.ClassRule;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.keycloak.OAuth2Constants; import org.keycloak.OAuth2Constants;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.FederatedIdentityModel; import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
@ -150,6 +151,37 @@ public abstract class AbstractIdentityProviderTest {
} }
} }
@Test
public void testDisabledForApplication() {
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
RealmModel realm = getRealm();
ApplicationModel applicationModel = realm.getApplicationByName("test-app");
List<String> allowedIdentityProviders = applicationModel.getAllowedIdentityProviders();
assertTrue(allowedIdentityProviders.contains(identityProviderModel.getId()));
allowedIdentityProviders.remove(identityProviderModel.getId());
this.driver.navigate().to("http://localhost:8081/test-app/");
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/login"));
try {
this.driver.findElement(By.className(getProviderId()));
fail("Provider [" + getProviderId() + "] not disabled.");
} catch (NoSuchElementException nsee) {
}
allowedIdentityProviders.add(identityProviderModel.getId());
applicationModel.updateAllowedIdentityProviders(allowedIdentityProviders);
this.driver.navigate().to("http://localhost:8081/test-app/");
this.driver.findElement(By.className(getProviderId()));
}
@Test @Test
public void testUserAlreadyExistsWhenUpdatingProfile() { public void testUserAlreadyExistsWhenUpdatingProfile() {
this.driver.navigate().to("http://localhost:8081/test-app/"); this.driver.navigate().to("http://localhost:8081/test-app/");

View file

@ -45,7 +45,6 @@ import java.util.Set;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
/** /**
@ -114,25 +113,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertFalse(identityProviderModel.isAuthenticateByDefault()); assertFalse(identityProviderModel.isAuthenticateByDefault());
} }
@Test
public void testRemoveIdentityProvider() throws Exception {
RealmModel realm = installTestRealm();
List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
assertFalse(identityProviders.isEmpty());
IdentityProviderModel identityProviderModel = identityProviders.get(0);
String expectedId = identityProviderModel.getId();
realm.removeIdentityProviderById(expectedId);
commit();
realm = this.realmManager.getRealm(realm.getId());
assertNull(realm.getIdentityProviderById(expectedId));
}
private void assertIdentityProviderConfig(List<IdentityProviderModel> identityProviders) { private void assertIdentityProviderConfig(List<IdentityProviderModel> identityProviders) {
assertFalse(identityProviders.isEmpty()); assertFalse(identityProviders.isEmpty());

View file

@ -185,9 +185,20 @@
"redirectUris": [ "redirectUris": [
"/test-app/*" "/test-app/*"
], ],
"webOrigins": []
},
{
"name": "test-app-with-allowed-providers",
"enabled": true,
"publicClient": true,
"adminUrl": "http://localhost:8081/auth",
"baseUrl": "http://localhost:8081/auth",
"redirectUris": [
"/test-app/*"
],
"webOrigins": [], "webOrigins": [],
"allowedIdentityProviders": [ "allowedIdentityProviders": [
"model-oidc-idp" "kc-oidc-idp"
] ]
} }
], ],

View file

@ -15,6 +15,7 @@
"identityProviders" : [ "identityProviders" : [
{ {
"providerId" : "google", "providerId" : "google",
"id" : "google",
"name" : "Google", "name" : "Google",
"enabled": true, "enabled": true,
"config": { "config": {