/*
* 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.model;
import org.junit.Assert;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.Constants;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.ldap.mappers.FullNameLDAPStorageMapper;
import org.keycloak.storage.ldap.mappers.FullNameLDAPStorageMapperFactory;
import org.keycloak.testsuite.federation.DummyUserFederationProviderFactory;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ImportTest extends AbstractModelTest {
@Test
public void demoDelete() throws Exception {
// was having trouble deleting this realm from admin console
RealmRepresentation rep = AbstractModelTest.loadJson("model/testrealm2.json");
RealmModel realm = realmManager.importRealm(rep);
commit();
realm = realmManager.getRealmByName("demo-delete");
realmManager.removeRealm(realm);
}
@Test
public void install() throws Exception {
RealmRepresentation rep = AbstractModelTest.loadJson("model/testrealm.json");
rep.setId("demo");
RealmModel realm = realmManager.importRealm(rep);
// Commit after import
commit();
realm = realmManager.getRealm("demo");
assertDataImportedInRealm(realmManager.getSession(), realm);
commit();
realm = realmManager.getRealm("demo");
realmManager.removeRealm(realm);
}
// Moved to static method, so it's possible to test this from other places too (for example export-import tests)
/*
BIG HELPFUL HINT!!!!
WHEN YOU MIGRATE THIS CLASS YOU DO NOT NEED TO MIGRATE THIS METHOD.
IT HAS ALREADY BEEN IMPLEMENTED IN THE NEW ARQUILLIAN TESTSUTE.
SEE org.keycloak.testsuite.exportimport.ExportImportUtil
*/
public static void assertDataImportedInRealm(KeycloakSession session, RealmModel realm) {
Assert.assertTrue(realm.isVerifyEmail());
Assert.assertEquals(3600000, realm.getOfflineSessionIdleTimeout());
Assert.assertEquals(1500, realm.getAccessTokenLifespanForImplicitFlow());
List<RequiredCredentialModel> creds = realm.getRequiredCredentials();
Assert.assertEquals(1, creds.size());
RequiredCredentialModel cred = creds.get(0);
Assert.assertEquals("password", cred.getFormLabel());
Assert.assertEquals(4, realm.getDefaultRoles().size());
Assert.assertNotNull(realm.getRole("foo"));
Assert.assertNotNull(realm.getRole("bar"));
UserModel user = session.users().getUserByUsername("loginclient", realm);
Assert.assertNotNull(user);
Assert.assertEquals(0, session.users().getFederatedIdentities(user, realm).size());
List<ClientModel> resources = realm.getClients();
Assert.assertEquals(8, resources.size());
// Test applications imported
ClientModel application = realm.getClientByClientId("Application");
ClientModel otherApp = realm.getClientByClientId("OtherApp");
ClientModel accountApp = realm.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
ClientModel nonExisting = realm.getClientByClientId("NonExisting");
Assert.assertNotNull(application);
Assert.assertNotNull(otherApp);
Assert.assertNull(nonExisting);
List<ClientModel> clients = realm.getClients();
Assert.assertEquals(8, clients.size());
Assert.assertTrue(clients.contains(application));
Assert.assertTrue(clients.contains(otherApp));
Assert.assertTrue(clients.contains(accountApp));
realm.getClients().containsAll(clients);
Assert.assertEquals("Applicationn", application.getName());
Assert.assertEquals(50, application.getNodeReRegistrationTimeout());
Map<String, Integer> appRegisteredNodes = application.getRegisteredNodes();
Assert.assertEquals(2, appRegisteredNodes.size());
Assert.assertTrue(10 == appRegisteredNodes.get("node1"));
Assert.assertTrue(20 == appRegisteredNodes.get("172.10.15.20"));
// test clientAuthenticatorType
Assert.assertEquals(application.getClientAuthenticatorType(), "client-secret");
Assert.assertEquals(otherApp.getClientAuthenticatorType(), "client-jwt");
// Test finding applications by ID
Assert.assertNull(realm.getClientById("982734"));
Assert.assertEquals(application, realm.getClientById(application.getId()));
// Test role mappings
UserModel admin = session.users().getUserByUsername("admin", realm);
// user without creation timestamp in import
Assert.assertNull(admin.getCreatedTimestamp());
Set<RoleModel> allRoles = admin.getRoleMappings();
Assert.assertEquals(3, allRoles.size());
Assert.assertTrue(allRoles.contains(realm.getRole("admin")));
Assert.assertTrue(allRoles.contains(application.getRole("app-admin")));
Assert.assertTrue(allRoles.contains(otherApp.getRole("otherapp-admin")));
Assert.assertTrue(application.getRole("app-admin").isScopeParamRequired());
Assert.assertFalse(otherApp.getRole("otherapp-admin").isScopeParamRequired());
Assert.assertFalse(otherApp.getRole("otherapp-user").isScopeParamRequired());
UserModel wburke = session.users().getUserByUsername("wburke", realm);
// user with creation timestamp in import
Assert.assertEquals(new Long(123654), wburke.getCreatedTimestamp());
allRoles = wburke.getRoleMappings();
Assert.assertEquals(2, allRoles.size());
Assert.assertFalse(allRoles.contains(realm.getRole("admin")));
Assert.assertTrue(allRoles.contains(application.getRole("app-user")));
Assert.assertTrue(allRoles.contains(otherApp.getRole("otherapp-user")));
Assert.assertEquals(0, wburke.getRealmRoleMappings().size());
UserModel loginclient = session.users().getUserByUsername("loginclient", realm);
// user with creation timestamp as string in import
Assert.assertEquals(new Long(123655), loginclient.getCreatedTimestamp());
Set<RoleModel> realmRoles = admin.getRealmRoleMappings();
Assert.assertEquals(1, realmRoles.size());
Assert.assertEquals("admin", realmRoles.iterator().next().getName());
Set<RoleModel> appRoles = admin.getClientRoleMappings(application);
Assert.assertEquals(1, appRoles.size());
Assert.assertEquals("app-admin", appRoles.iterator().next().getName());
// Test attributes
Map<String, List<String>> attrs = wburke.getAttributes();
Assert.assertEquals(1, attrs.size());
List<String> attrVals = attrs.get("email");
Assert.assertEquals(1, attrVals.size());
Assert.assertEquals("bburke@redhat.com", attrVals.get(0));
attrs = admin.getAttributes();
Assert.assertEquals(2, attrs.size());
attrVals = attrs.get("key1");
Assert.assertEquals(1, attrVals.size());
Assert.assertEquals("val1", attrVals.get(0));
attrVals = attrs.get("key2");
Assert.assertEquals(2, attrVals.size());
Assert.assertTrue(attrVals.contains("val21") && attrVals.contains("val22"));
// Test client
ClientModel oauthClient = realm.getClientByClientId("oauthclient");
Assert.assertEquals("clientpassword", oauthClient.getSecret());
Assert.assertEquals(true, oauthClient.isEnabled());
Assert.assertNotNull(oauthClient);
// Test scope relationship
Set<RoleModel> allScopes = oauthClient.getScopeMappings();
Assert.assertEquals(2, allScopes.size());
Assert.assertTrue(allScopes.contains(realm.getRole("admin")));
Assert.assertTrue(allScopes.contains(application.getRole("app-user")));
Set<RoleModel> realmScopes = oauthClient.getRealmScopeMappings();
Assert.assertTrue(realmScopes.contains(realm.getRole("admin")));
Set<RoleModel> appScopes = KeycloakModelUtils.getClientScopeMappings(application, oauthClient);//application.getClientScopeMappings(oauthClient);
Assert.assertTrue(appScopes.contains(application.getRole("app-user")));
// Test social linking
UserModel socialUser = session.users().getUserByUsername("mySocialUser", realm);
Set<FederatedIdentityModel> socialLinks = session.users().getFederatedIdentities(socialUser, realm);
Assert.assertEquals(3, socialLinks.size());
boolean facebookFound = false;
boolean googleFound = false;
boolean twitterFound = false;
for (FederatedIdentityModel federatedIdentityModel : socialLinks) {
if ("facebook".equals(federatedIdentityModel.getIdentityProvider())) {
facebookFound = true;
Assert.assertEquals(federatedIdentityModel.getUserId(), "facebook1");
Assert.assertEquals(federatedIdentityModel.getUserName(), "fbuser1");
} else if ("google".equals(federatedIdentityModel.getIdentityProvider())) {
googleFound = true;
Assert.assertEquals(federatedIdentityModel.getUserId(), "google1");
Assert.assertEquals(federatedIdentityModel.getUserName(), "mysocialuser@gmail.com");
} else if ("twitter".equals(federatedIdentityModel.getIdentityProvider())) {
twitterFound = true;
Assert.assertEquals(federatedIdentityModel.getUserId(), "twitter1");
Assert.assertEquals(federatedIdentityModel.getUserName(), "twuser1");
}
}
Assert.assertTrue(facebookFound && twitterFound && googleFound);
UserModel foundSocialUser = session.users().getUserByFederatedIdentity(new FederatedIdentityModel("facebook", "facebook1", "fbuser1"), realm);
Assert.assertEquals(foundSocialUser.getUsername(), socialUser.getUsername());
Assert.assertNull(session.users().getUserByFederatedIdentity(new FederatedIdentityModel("facebook", "not-existing", "not-existing"), realm));
FederatedIdentityModel foundSocialLink = session.users().getFederatedIdentity(socialUser, "facebook", realm);
Assert.assertEquals("facebook1", foundSocialLink.getUserId());
Assert.assertEquals("fbuser1", foundSocialLink.getUserName());
Assert.assertEquals("facebook", foundSocialLink.getIdentityProvider());
// Test removing social link
Assert.assertTrue(session.users().removeFederatedIdentity(realm, socialUser, "facebook"));
Assert.assertNull(session.users().getFederatedIdentity(socialUser, "facebook", realm));
Assert.assertFalse(session.users().removeFederatedIdentity(realm, socialUser, "facebook"));
session.users().addFederatedIdentity(realm, socialUser, new FederatedIdentityModel("facebook", "facebook1", "fbuser1"));
// Test smtp config
Map<String, String> smtpConfig = realm.getSmtpConfig();
Assert.assertTrue(smtpConfig.size() == 3);
Assert.assertEquals("auto@keycloak.org", smtpConfig.get("from"));
Assert.assertEquals("localhost", smtpConfig.get("host"));
Assert.assertEquals("3025", smtpConfig.get("port"));
// Test identity providers
List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
Assert.assertEquals(1, identityProviders.size());
IdentityProviderModel google = identityProviders.get(0);
Assert.assertEquals("google1", google.getAlias());
Assert.assertEquals("google", google.getProviderId());
Assert.assertTrue(google.isEnabled());
Assert.assertEquals("googleId", google.getConfig().get("clientId"));
Assert.assertEquals("googleSecret", google.getConfig().get("clientSecret"));
// Test federation providers
List<UserStorageProviderModel> storageProviders = realm.getUserStorageProviders();
Assert.assertTrue(storageProviders.size() == 2);
UserStorageProviderModel ldap1 = storageProviders.get(0);
Assert.assertEquals("MyLDAPProvider1", ldap1.getName());
Assert.assertEquals("ldap", ldap1.getProviderId());
Assert.assertEquals(1, ldap1.getPriority());
Assert.assertEquals("ldap://foo", ldap1.getConfig().getFirst(LDAPConstants.CONNECTION_URL));
UserStorageProviderModel ldap2 = storageProviders.get(1);
Assert.assertEquals("MyLDAPProvider2", ldap2.getName());
Assert.assertEquals("ldap://bar", ldap2.getConfig().getFirst(LDAPConstants.CONNECTION_URL));
// Test federation mappers
List<ComponentModel> fedMappers1 = realm.getComponents(ldap1.getId());
ComponentModel fullNameMapper = fedMappers1.iterator().next();
Assert.assertEquals("FullNameMapper", fullNameMapper.getName());
Assert.assertEquals(FullNameLDAPStorageMapperFactory.PROVIDER_ID, fullNameMapper.getProviderId());
Assert.assertEquals(ldap1.getId(), fullNameMapper.getParentId());
Assert.assertEquals("cn", fullNameMapper.getConfig().getFirst(FullNameLDAPStorageMapper.LDAP_FULL_NAME_ATTRIBUTE));
// Assert that federation link wasn't created during import
DummyUserFederationProviderFactory factory = (DummyUserFederationProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, "dummy");
Assert.assertNull(factory.create(session, null).getUserByUsername("wburke", realm));
// Test builtin authentication flows
AuthenticationFlowModel clientFlow = realm.getClientAuthenticationFlow();
Assert.assertEquals(DefaultAuthenticationFlows.CLIENT_AUTHENTICATION_FLOW, clientFlow.getAlias());
Assert.assertNotNull(realm.getAuthenticationFlowById(clientFlow.getId()));
Assert.assertTrue(realm.getAuthenticationExecutions(clientFlow.getId()).size() > 0);
AuthenticationFlowModel resetFlow = realm.getResetCredentialsFlow();
Assert.assertEquals(DefaultAuthenticationFlows.RESET_CREDENTIALS_FLOW, resetFlow.getAlias());
Assert.assertNotNull(realm.getAuthenticationFlowById(resetFlow.getId()));
Assert.assertTrue(realm.getAuthenticationExecutions(resetFlow.getId()).size() > 0);
// Test protocol mappers. Default application has all the builtin protocol mappers. OtherApp just gss credential
Assert.assertNotNull(application.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "username"));
Assert.assertNotNull(application.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "email"));
Assert.assertNotNull(application.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "given name"));
Assert.assertNull(application.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME));
Assert.assertEquals(1, otherApp.getProtocolMappers().size());
Assert.assertNull(otherApp.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "username"));
ProtocolMapperModel gssCredentialMapper = otherApp.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME);
assertGssProtocolMapper(gssCredentialMapper);
// Test clientTemplates
List<ClientTemplateModel> clientTemplates = realm.getClientTemplates();
Assert.assertEquals(1, clientTemplates.size());
ClientTemplateModel clientTemplate = clientTemplates.get(0);
Assert.assertEquals("foo-template", clientTemplate.getName());
Assert.assertEquals("foo-template-desc", clientTemplate.getDescription());
Assert.assertEquals(OIDCLoginProtocol.LOGIN_PROTOCOL, clientTemplate.getProtocol());
Assert.assertEquals(1, clientTemplate.getProtocolMappers().size());
ProtocolMapperModel templateGssCredentialMapper = clientTemplate.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME);
assertGssProtocolMapper(templateGssCredentialMapper);
// Test client template scopes
Set<RoleModel> allClientTemplateScopes = clientTemplate.getScopeMappings();
Assert.assertEquals(3, allClientTemplateScopes.size());
Assert.assertTrue(allClientTemplateScopes.contains(realm.getRole("admin")));
Assert.assertTrue(allClientTemplateScopes.contains(application.getRole("app-user")));
Assert.assertTrue(allClientTemplateScopes.contains(application.getRole("app-admin")));
Set<RoleModel> clientTemplateRealmScopes = clientTemplate.getRealmScopeMappings();
Assert.assertTrue(clientTemplateRealmScopes.contains(realm.getRole("admin")));
Set<RoleModel> clientTemplateAppScopes = KeycloakModelUtils.getClientScopeMappings(application, clientTemplate);//application.getClientScopeMappings(oauthClient);
Assert.assertTrue(clientTemplateAppScopes.contains(application.getRole("app-user")));
Assert.assertTrue(clientTemplateAppScopes.contains(application.getRole("app-admin")));
// Test user consents
admin = session.users().getUserByUsername("admin", realm);
Assert.assertEquals(2, session.users().getConsents(realm, admin.getId()).size());
UserConsentModel appAdminConsent = session.users().getConsentByClient(realm, admin.getId(), application.getId());
Assert.assertEquals(2, appAdminConsent.getGrantedRoles().size());
Assert.assertTrue(appAdminConsent.getGrantedProtocolMappers() == null || appAdminConsent.getGrantedProtocolMappers().isEmpty());
Assert.assertTrue(appAdminConsent.isRoleGranted(realm.getRole("admin")));
Assert.assertTrue(appAdminConsent.isRoleGranted(application.getRole("app-admin")));
UserConsentModel otherAppAdminConsent = session.users().getConsentByClient(realm, admin.getId(), otherApp.getId());
Assert.assertEquals(1, otherAppAdminConsent.getGrantedRoles().size());
Assert.assertEquals(1, otherAppAdminConsent.getGrantedProtocolMappers().size());
Assert.assertTrue(otherAppAdminConsent.isRoleGranted(realm.getRole("admin")));
Assert.assertFalse(otherAppAdminConsent.isRoleGranted(application.getRole("app-admin")));
Assert.assertTrue(otherAppAdminConsent.isProtocolMapperGranted(gssCredentialMapper));
Assert.assertTrue(application.isStandardFlowEnabled());
Assert.assertTrue(application.isImplicitFlowEnabled());
Assert.assertTrue(application.isDirectAccessGrantsEnabled());
Assert.assertFalse(otherApp.isStandardFlowEnabled());
Assert.assertFalse(otherApp.isImplicitFlowEnabled());
Assert.assertFalse(otherApp.isDirectAccessGrantsEnabled());
// Test service accounts
Assert.assertFalse(application.isServiceAccountsEnabled());
Assert.assertTrue(otherApp.isServiceAccountsEnabled());
Assert.assertNull(session.users().getServiceAccount(application));
UserModel linked = session.users().getServiceAccount(otherApp);
Assert.assertNotNull(linked);
Assert.assertEquals("my-service-user", linked.getUsername());
}
@Test
public void install2() throws Exception {
RealmManager manager = realmManager;
RealmRepresentation rep = AbstractModelTest.loadJson("model/testrealm-demo.json");
rep.setId("demo");
RealmModel realm =manager.importRealm(rep);
Assert.assertEquals(600, realm.getAccessCodeLifespanUserAction());
Assert.assertEquals(Constants.DEFAULT_ACCESS_TOKEN_LIFESPAN_FOR_IMPLICIT_FLOW_TIMEOUT, realm.getAccessTokenLifespanForImplicitFlow());
Assert.assertEquals(Constants.DEFAULT_OFFLINE_SESSION_IDLE_TIMEOUT, realm.getOfflineSessionIdleTimeout());
verifyRequiredCredentials(realm.getRequiredCredentials(), "password");
}
private void verifyRequiredCredentials(List<RequiredCredentialModel> requiredCreds, String expectedType) {
Assert.assertEquals(1, requiredCreds.size());
Assert.assertEquals(expectedType, requiredCreds.get(0).getType());
}
private static void assertGssProtocolMapper(ProtocolMapperModel gssCredentialMapper) {
Assert.assertEquals(KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME, gssCredentialMapper.getName());
Assert.assertEquals( OIDCLoginProtocol.LOGIN_PROTOCOL, gssCredentialMapper.getProtocol());
Assert.assertEquals(UserSessionNoteMapper.PROVIDER_ID, gssCredentialMapper.getProtocolMapper());
String includeInAccessToken = gssCredentialMapper.getConfig().get(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
String includeInIdToken = gssCredentialMapper.getConfig().get(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
Assert.assertTrue(includeInAccessToken.equalsIgnoreCase("true"));
Assert.assertTrue(includeInIdToken == null || Boolean.parseBoolean(includeInIdToken) == false);
}
}