keycloak-aplcache
Changes
testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserFederationStorageTest.java 27(+27 -0)
testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorage.java 156(+156 -0)
Details
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index 6d7ea98..d6837aa 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -1019,18 +1019,11 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
copy.add(entity);
}
- Collections.sort(copy, new Comparator<StorageProviderEntity>() {
-
- @Override
- public int compare(StorageProviderEntity o1, StorageProviderEntity o2) {
- return o1.getPriority() - o2.getPriority();
- }
-
- });
List<StorageProviderModel> result = new LinkedList<>();
for (StorageProviderEntity entity : copy) {
result.add(toModel(entity));
}
+ Collections.sort(result, StorageProviderModel.comparator);
return Collections.unmodifiableList(result);
}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index 5c9c589..cb6bba7 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -1311,20 +1311,13 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
copy.add(entity);
}
- Collections.sort(copy, new Comparator<StorageProviderEntity>() {
-
- @Override
- public int compare(StorageProviderEntity o1, StorageProviderEntity o2) {
- return o1.getPriority() - o2.getPriority();
- }
-
- });
List<StorageProviderModel> result = new LinkedList<>();
for (StorageProviderEntity entity : copy) {
result.add(new StorageProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName()
));
}
+ Collections.sort(result, StorageProviderModel.comparator);
return Collections.unmodifiableList(result);
}
diff --git a/saml-core/src/main/java/org/keycloak/saml/SPMetadataDescriptor.java b/saml-core/src/main/java/org/keycloak/saml/SPMetadataDescriptor.java
index 4d83d39..e6c10af 100755
--- a/saml-core/src/main/java/org/keycloak/saml/SPMetadataDescriptor.java
+++ b/saml-core/src/main/java/org/keycloak/saml/SPMetadataDescriptor.java
@@ -26,24 +26,25 @@ public class SPMetadataDescriptor {
String descriptor =
"<EntityDescriptor xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\" entityID=\"" + entityId + "\">\n" +
" <SPSSODescriptor AuthnRequestsSigned=\"" + wantAuthnRequestsSigned + "\"\n" +
- " protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol http://schemas.xmlsoap.org/ws/2003/07/secext\">\n" +
+ " protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol http://schemas.xmlsoap.org/ws/2003/07/secext\">\n";
+ if (wantAuthnRequestsSigned) {
+ descriptor +=
+ " <KeyDescriptor use=\"signing\">\n" +
+ " <dsig:KeyInfo xmlns:dsig=\"http://www.w3.org/2000/09/xmldsig#\">\n" +
+ " <dsig:X509Data>\n" +
+ " <dsig:X509Certificate>\n" + certificatePem + "\n" +
+ " </dsig:X509Certificate>\n" +
+ " </dsig:X509Data>\n" +
+ " </dsig:KeyInfo>\n" +
+ " </KeyDescriptor>\n";
+ }
+ descriptor +=
" <SingleLogoutService Binding=\"" + binding + "\" Location=\"" + logoutEndpoint + "\"/>\n" +
" <NameIDFormat>" + nameIDPolicyFormat + "\n" +
" </NameIDFormat>\n" +
" <AssertionConsumerService\n" +
" Binding=\"" + binding + "\" Location=\"" + assertionEndpoint + "\"\n" +
" index=\"1\" isDefault=\"true\" />\n";
- if (wantAuthnRequestsSigned) {
- descriptor +=
- " <KeyDescriptor use=\"signing\">\n" +
- " <dsig:KeyInfo xmlns:dsig=\"http://www.w3.org/2000/09/xmldsig#\">\n" +
- " <dsig:X509Data>\n" +
- " <dsig:X509Certificate>\n" + certificatePem + "\n" +
- " </dsig:X509Certificate>\n" +
- " </dsig:X509Data>\n" +
- " </dsig:KeyInfo>\n" +
- " </KeyDescriptor>\n";
- }
descriptor +=
" </SPSSODescriptor>\n" +
"</EntityDescriptor>\n";
diff --git a/server-spi/src/main/java/org/keycloak/models/UserProvider.java b/server-spi/src/main/java/org/keycloak/models/UserProvider.java
index 982453e..24b6106 100755
--- a/server-spi/src/main/java/org/keycloak/models/UserProvider.java
+++ b/server-spi/src/main/java/org/keycloak/models/UserProvider.java
@@ -22,7 +22,7 @@ import org.keycloak.storage.StorageProviderModel;
import org.keycloak.storage.user.UserCredentialValidatorProvider;
import org.keycloak.storage.user.UserLookupProvider;
import org.keycloak.storage.user.UserQueryProvider;
-import org.keycloak.storage.user.UserUpdateProvider;
+import org.keycloak.storage.user.UserRegistrationProvider;
import java.util.List;
import java.util.Set;
@@ -35,7 +35,7 @@ public interface UserProvider extends Provider,
UserLookupProvider,
UserQueryProvider,
UserCredentialValidatorProvider,
- UserUpdateProvider {
+ UserRegistrationProvider {
// Note: The reason there are so many query methods here is for layering a cache on top of an persistent KeycloakSession
public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink);
diff --git a/server-spi/src/main/java/org/keycloak/storage/StorageProviderModel.java b/server-spi/src/main/java/org/keycloak/storage/StorageProviderModel.java
index 910df81..823a500 100755
--- a/server-spi/src/main/java/org/keycloak/storage/StorageProviderModel.java
+++ b/server-spi/src/main/java/org/keycloak/storage/StorageProviderModel.java
@@ -18,6 +18,7 @@
package org.keycloak.storage;
import java.io.Serializable;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
@@ -29,6 +30,13 @@ import java.util.Map;
*/
public class StorageProviderModel implements Serializable {
+ public static Comparator<StorageProviderModel> comparator = new Comparator<StorageProviderModel>() {
+ @Override
+ public int compare(StorageProviderModel o1, StorageProviderModel o2) {
+ return o1.priority - o2.priority;
+ }
+ };
+
private String id;
private String providerName;
private Map<String, String> config = new HashMap<String, String>();
diff --git a/server-spi/src/main/java/org/keycloak/storage/UserStorageManager.java b/server-spi/src/main/java/org/keycloak/storage/UserStorageManager.java
index db39190..b6e6028 100755
--- a/server-spi/src/main/java/org/keycloak/storage/UserStorageManager.java
+++ b/server-spi/src/main/java/org/keycloak/storage/UserStorageManager.java
@@ -38,7 +38,7 @@ import org.keycloak.storage.user.UserLookupProvider;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserProvider;
import org.keycloak.storage.user.UserQueryProvider;
-import org.keycloak.storage.user.UserUpdateProvider;
+import org.keycloak.storage.user.UserRegistrationProvider;
import org.keycloak.models.utils.CredentialValidation;
import org.keycloak.storage.federated.UserFederatedStorageProvider;
@@ -106,7 +106,7 @@ public class UserStorageManager implements UserProvider {
@Override
public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
- UserUpdateProvider registry = getFirstStorageProvider(realm, UserUpdateProvider.class);
+ UserRegistrationProvider registry = getFirstStorageProvider(realm, UserRegistrationProvider.class);
if (registry != null) {
return registry.addUser(realm, id, username, addDefaultRoles, addDefaultRequiredActions);
}
@@ -115,7 +115,7 @@ public class UserStorageManager implements UserProvider {
@Override
public UserModel addUser(RealmModel realm, String username) {
- UserUpdateProvider registry = getFirstStorageProvider(realm, UserUpdateProvider.class);
+ UserRegistrationProvider registry = getFirstStorageProvider(realm, UserRegistrationProvider.class);
if (registry != null) {
return registry.addUser(realm, username);
}
@@ -139,7 +139,7 @@ public class UserStorageManager implements UserProvider {
if (storageId.getProviderId() == null) {
return localStorage().removeUser(realm, user);
}
- UserUpdateProvider registry = (UserUpdateProvider)getStorageProvider(realm, storageId.getProviderId());
+ UserRegistrationProvider registry = (UserRegistrationProvider)getStorageProvider(realm, storageId.getProviderId());
if (registry == null) {
throw new ModelException("Could not resolve StorageProvider: " + storageId.getProviderId());
}
@@ -446,11 +446,11 @@ public class UserStorageManager implements UserProvider {
@Override
public void grantToAllUsers(RealmModel realm, RoleModel role) {
// not federation-aware for now
- List<UserUpdateProvider> storageProviders = getStorageProviders(realm, UserUpdateProvider.class);
- LinkedList<UserUpdateProvider> providers = new LinkedList<>();
+ List<UserRegistrationProvider> storageProviders = getStorageProviders(realm, UserRegistrationProvider.class);
+ LinkedList<UserRegistrationProvider> providers = new LinkedList<>();
providers.add(localStorage());
providers.addAll(storageProviders);
- for (UserUpdateProvider provider : providers) {
+ for (UserRegistrationProvider provider : providers) {
provider.grantToAllUsers(realm, role);
}
}
diff --git a/services/src/main/resources/idp-metadata-template.xml b/services/src/main/resources/idp-metadata-template.xml
index 8e4bdb8..6b3d5ec 100755
--- a/services/src/main/resources/idp-metadata-template.xml
+++ b/services/src/main/resources/idp-metadata-template.xml
@@ -18,15 +18,30 @@
<EntitiesDescriptor Name="urn:keycloak"
xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
- xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<EntityDescriptor entityID="${idp.entityID}">
<IDPSSODescriptor WantAuthnRequestsSigned="true"
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
- <NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
- <NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
+
+ <KeyDescriptor use="signing">
+ <dsig:KeyInfo>
+ <dsig:X509Data>
+ <dsig:X509Certificate>
+ ${idp.signing.certificate}
+ </dsig:X509Certificate>
+ </dsig:X509Data>
+ </dsig:KeyInfo>
+ </KeyDescriptor>
+ <SingleLogoutService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
+ Location="${idp.sls.HTTP-POST}" />
+ <SingleLogoutService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
+ Location="${idp.sso.HTTP-Redirect}" />
+ <NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
+ <NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
-
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="${idp.sso.HTTP-POST}" />
<SingleSignOnService
@@ -35,21 +50,6 @@
<SingleSignOnService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="${idp.sso.HTTP-POST}" />
- <SingleLogoutService
- Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
- Location="${idp.sls.HTTP-POST}" />
- <SingleLogoutService
- Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
- Location="${idp.sso.HTTP-Redirect}" />
- <KeyDescriptor use="signing">
- <dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
- <dsig:X509Data>
- <dsig:X509Certificate>
- ${idp.signing.certificate}
- </dsig:X509Certificate>
- </dsig:X509Data>
- </dsig:KeyInfo>
- </KeyDescriptor>
</IDPSSODescriptor>
</EntityDescriptor>
</EntitiesDescriptor>
\ No newline at end of file
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserFederationStorageTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserFederationStorageTest.java
index 58d0ed0..ee55d14 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserFederationStorageTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserFederationStorageTest.java
@@ -29,6 +29,7 @@ import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.cache.infinispan.UserAdapter;
import org.keycloak.services.managers.RealmManager;
+import org.keycloak.storage.StorageId;
import org.keycloak.storage.StorageProviderModel;
import org.keycloak.testsuite.OAuthClient;
import org.keycloak.testsuite.pages.AppPage;
@@ -47,12 +48,18 @@ import java.util.Set;
* @version $Revision: 1 $
*/
public class UserFederationStorageTest {
+ public static StorageProviderModel memoryProvider = null;
@ClassRule
public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() {
@Override
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
StorageProviderModel model = new StorageProviderModel();
+ model.setDisplayName("memory");
+ model.setPriority(0);
+ model.setProviderName(UserMapStorageFactory.PROVIDER_ID);
+ memoryProvider = appRealm.addStorageProvider(model);
+ model = new StorageProviderModel();
model.setDisplayName("read-only-user-props");
model.setPriority(1);
model.setProviderName(UserPropertyFileStorageFactory.PROVIDER_ID);
@@ -238,4 +245,24 @@ public class UserFederationStorageTest {
keycloakRule.stopSession(session, true);
}
+ @Test
+ public void testRegistration() {
+ KeycloakSession session = keycloakRule.startSession();
+ RealmModel realm = session.realms().getRealmByName("test");
+ UserModel user = session.users().addUser(realm, "memuser");
+ user.updateCredential(UserCredentialModel.password("password"));
+ keycloakRule.stopSession(session, true);
+ loginSuccessAndLogout("memuser", "password");
+
+ session = keycloakRule.startSession();
+ realm = session.realms().getRealmByName("test");
+ user = session.users().getUserByUsername("memuser", realm);
+ Assert.assertEquals(memoryProvider.getId(), StorageId.resolveProviderId(user));
+ Assert.assertEquals(0, user.getCredentialsDirectly().size());
+ session.users().removeUser(realm, user);
+ Assert.assertNull(session.users().getUserByUsername("memuser", realm));
+ keycloakRule.stopSession(session, true);
+
+ }
+
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorage.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorage.java
new file mode 100644
index 0000000..daed4ad
--- /dev/null
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorage.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.testsuite.federation.storage;
+
+import org.keycloak.models.GroupModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.storage.StorageId;
+import org.keycloak.storage.StorageProvider;
+import org.keycloak.storage.StorageProviderModel;
+import org.keycloak.storage.adapter.AbstractUserAdapterFederatedStorage;
+import org.keycloak.storage.user.UserCredentialValidatorProvider;
+import org.keycloak.storage.user.UserLookupProvider;
+import org.keycloak.storage.user.UserRegistrationProvider;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserMapStorage implements UserLookupProvider, StorageProvider, UserCredentialValidatorProvider, UserRegistrationProvider {
+
+ protected Map<String, String> userPasswords;
+ protected StorageProviderModel model;
+ protected KeycloakSession session;
+
+ public UserMapStorage(KeycloakSession session, StorageProviderModel model, Map<String, String> userPasswords) {
+ this.session = session;
+ this.model = model;
+ this.userPasswords = userPasswords;
+ }
+
+
+ @Override
+ public UserModel getUserById(String id, RealmModel realm) {
+ StorageId storageId = new StorageId(id);
+ final String username = storageId.getStorageId();
+ if (!userPasswords.containsKey(username)) return null;
+
+ return createUser(realm, username);
+ }
+
+ private UserModel createUser(RealmModel realm, String username) {
+ return new AbstractUserAdapterFederatedStorage(session, realm, model) {
+ @Override
+ public String getUsername() {
+ return username;
+ }
+
+ @Override
+ public void setUsername(String username) {
+ throw new RuntimeException("Unsupported");
+ }
+
+ @Override
+ public void updateCredential(UserCredentialModel cred) {
+ if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+ userPasswords.put(username, cred.getValue());
+ } else {
+ super.updateCredential(cred);
+ }
+ }
+ };
+ }
+
+ @Override
+ public UserModel getUserByUsername(String username, RealmModel realm) {
+ if (!userPasswords.containsKey(username)) return null;
+
+ return createUser(realm, username);
+ }
+
+ @Override
+ public UserModel getUserByEmail(String email, RealmModel realm) {
+ return null;
+ }
+
+ @Override
+ public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
+ userPasswords.put(username, "");
+ return createUser(realm, username);
+ }
+
+ @Override
+ public UserModel addUser(RealmModel realm, String username) {
+ userPasswords.put(username, "");
+ return createUser(realm, username);
+ }
+
+ @Override
+ public boolean removeUser(RealmModel realm, UserModel user) {
+ return userPasswords.remove(user.getUsername()) != null;
+ }
+
+ @Override
+ public void grantToAllUsers(RealmModel realm, RoleModel role) {
+
+ }
+
+ @Override
+ public void preRemove(RealmModel realm) {
+
+ }
+
+ @Override
+ public void preRemove(RealmModel realm, GroupModel group) {
+
+ }
+
+ @Override
+ public void preRemove(RealmModel realm, RoleModel role) {
+
+ }
+
+ @Override
+ public void preRemove(RealmModel realm, StorageProviderModel model) {
+
+ }
+
+ @Override
+ public boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, List<UserCredentialModel> input) {
+ for (UserCredentialModel cred : input) {
+ if (!cred.getType().equals(UserCredentialModel.PASSWORD)) return false;
+ String password = (String)userPasswords.get(user.getUsername());
+ if (password == null) return false;
+ if (!password.equals(cred.getValue())) return false;
+ }
+ return true;
+ }
+
+
+
+ @Override
+ public void close() {
+
+ }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorageFactory.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorageFactory.java
new file mode 100644
index 0000000..f80a11d
--- /dev/null
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorageFactory.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.testsuite.federation.storage;
+
+import org.keycloak.Config;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.storage.StorageProvider;
+import org.keycloak.storage.StorageProviderFactory;
+import org.keycloak.storage.StorageProviderModel;
+
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserMapStorageFactory implements StorageProviderFactory<UserMapStorage> {
+
+
+ public static final String PROVIDER_ID = "user-password-map";
+
+ protected Map<String, String> userPasswords = new Hashtable<>();
+
+ @Override
+ public UserMapStorage getInstance(KeycloakSession session, StorageProviderModel model) {
+ return new UserMapStorage(session, model, userPasswords);
+ }
+
+ @Override
+ public String getId() {
+ return PROVIDER_ID;
+ }
+
+ @Override
+ public StorageProvider create(KeycloakSession session) {
+ return null;
+ }
+
+ @Override
+ public void init(Config.Scope config) {
+
+ }
+
+ @Override
+ public void postInit(KeycloakSessionFactory factory) {
+
+ }
+
+ @Override
+ public void close() {
+
+ }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/ValidationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/ValidationTest.java
new file mode 100644
index 0000000..43638e0
--- /dev/null
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/ValidationTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.testsuite.saml;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.keycloak.common.util.PemUtils;
+import org.keycloak.common.util.StreamUtil;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.protocol.saml.SamlProtocol;
+import org.keycloak.protocol.saml.SamlService;
+import org.keycloak.saml.SPMetadataDescriptor;
+import org.keycloak.services.resources.RealmsResource;
+import org.xml.sax.SAXException;
+
+import javax.ws.rs.core.UriInfo;
+import javax.xml.XMLConstants;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ValidationTest {
+
+ public static String getIDPMetadataDescriptor() throws IOException {
+ InputStream is = SamlService.class.getResourceAsStream("/idp-metadata-template.xml");
+ String template = StreamUtil.readString(is);
+ template = template.replace("${idp.entityID}", "http://keycloak.org/auth/realms/test");
+ template = template.replace("${idp.sso.HTTP-POST}", "http://keycloak.org/auth/realms/test/saml");
+ template = template.replace("${idp.sso.HTTP-Redirect}", "http://keycloak.org/auth/realms/test/saml");
+ template = template.replace("${idp.sls.HTTP-POST}", "http://keycloak.org/auth/realms/test/saml");
+ template = template.replace("${idp.signing.certificate}", KeycloakModelUtils.generateKeyPairCertificate("test").getCertificate());
+ return template;
+ }
+
+
+ @Test
+ @Ignore // ignore because it goes out to web
+ public void testIDPDescriptor() throws Exception {
+ URL schemaFile = getClass().getResource("/schema/saml/v2/saml-schema-metadata-2.0.xsd");
+ Source xmlFile = new StreamSource(new ByteArrayInputStream(getIDPMetadataDescriptor().getBytes()), "IDPSSODescriptor");
+ SchemaFactory schemaFactory = SchemaFactory
+ .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ Schema schema = schemaFactory.newSchema(schemaFile);
+ Validator validator = schema.newValidator();
+ try {
+ validator.validate(xmlFile);
+ System.out.println(xmlFile.getSystemId() + " is valid");
+ } catch (SAXException e) {
+ System.out.println(xmlFile.getSystemId() + " is NOT valid");
+ System.out.println("Reason: " + e.getLocalizedMessage());
+ Assert.fail();
+ }
+ }
+ @Test
+ @Ignore // ignore because it goes out to web
+ public void testBrokerExportDescriptor() throws Exception {
+ URL schemaFile = getClass().getResource("/schema/saml/v2/saml-schema-metadata-2.0.xsd");
+ Source xmlFile = new StreamSource(new ByteArrayInputStream(SPMetadataDescriptor.getSPDescriptor(
+ "POST", "http://realm/assertion", "http://realm/logout", true, "test", SamlProtocol.SAML_DEFAULT_NAMEID_FORMAT, KeycloakModelUtils.generateKeyPairCertificate("test").getCertificate()
+ ).getBytes()), "SP Descriptor");
+ SchemaFactory schemaFactory = SchemaFactory
+ .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ Schema schema = schemaFactory.newSchema(schemaFile);
+ Validator validator = schema.newValidator();
+ try {
+ validator.validate(xmlFile);
+ System.out.println(xmlFile.getSystemId() + " is valid");
+ } catch (SAXException e) {
+ System.out.println(xmlFile.getSystemId() + " is NOT valid");
+ System.out.println("Reason: " + e.getLocalizedMessage());
+ Assert.fail();
+ }
+ }
+}
diff --git a/testsuite/integration/src/test/resources/META-INF/services/org.keycloak.storage.StorageProviderFactory b/testsuite/integration/src/test/resources/META-INF/services/org.keycloak.storage.StorageProviderFactory
index 001e16b..efbed13 100644
--- a/testsuite/integration/src/test/resources/META-INF/services/org.keycloak.storage.StorageProviderFactory
+++ b/testsuite/integration/src/test/resources/META-INF/services/org.keycloak.storage.StorageProviderFactory
@@ -1 +1,2 @@
-org.keycloak.testsuite.federation.storage.UserPropertyFileStorageFactory
\ No newline at end of file
+org.keycloak.testsuite.federation.storage.UserPropertyFileStorageFactory
+org.keycloak.testsuite.federation.storage.UserMapStorageFactory
\ No newline at end of file