keycloak-aplcache
Changes
forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js 65(+45 -20)
forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html 24(+23 -1)
forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-list.html 2(+1 -1)
forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-create.html 3(+2 -1)
forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java 4(+2 -2)
integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java 14(+8 -6)
model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java 12(+12 -0)
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java 6(+6 -0)
saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorDescriptionConverter.java 185(+101 -84)
saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporter.java 21(+0 -21)
saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.exportimport.ClientDescriptionConverterFactory 1(+1 -0)
saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.exportimport.ClientImporterFactory 1(+0 -1)
services/src/main/java/org/keycloak/exportimport/KeycloakClientDescriptionConverter.java 44(+30 -14)
services/src/main/java/org/keycloak/protocol/oidc/representations/OIDCClientRepresentation.java 45(+45 -0)
services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java 16(+1 -15)
services/src/main/resources/META-INF/services/org.keycloak.exportimport.ClientDescriptionConverterFactory 2(+2 -0)
testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTest.java 2(+1 -1)
Details
diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.6.0.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.6.0.xml
index 24902d5..9d6e545 100644
--- a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.6.0.xml
+++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.6.0.xml
@@ -8,6 +8,10 @@
</column>
</addColumn>
+ <addColumn tableName="CLIENT">
+ <column name="ROOT_URL" type="VARCHAR(255)"/>
+ </addColumn>
+
<createTable tableName="OFFLINE_USER_SESSION">
<column name="USER_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
diff --git a/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java
index 020445e..7ad8c6e 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java
@@ -11,6 +11,7 @@ public class ClientRepresentation {
protected String id;
protected String clientId;
protected String name;
+ protected String rootUrl;
protected String adminUrl;
protected String baseUrl;
protected Boolean surrogateAuthRequired;
@@ -74,6 +75,14 @@ public class ClientRepresentation {
this.surrogateAuthRequired = surrogateAuthRequired;
}
+ public String getRootUrl() {
+ return rootUrl;
+ }
+
+ public void setRootUrl(String rootUrl) {
+ this.rootUrl = rootUrl;
+ }
+
public String getAdminUrl() {
return adminUrl;
}
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
index ae334e7..3cb3e60 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
@@ -564,8 +564,6 @@ module.controller('ClientRoleDetailCtrl', function($scope, realm, client, role,
module.controller('ClientImportCtrl', function($scope, $location, $upload, realm, serverInfo, Notifications) {
$scope.realm = realm;
- $scope.configFormats = serverInfo.clientImporters;
- $scope.configFormat = null;
$scope.files = [];
@@ -614,7 +612,6 @@ module.controller('ClientImportCtrl', function($scope, $location, $upload, realm
module.controller('ClientListCtrl', function($scope, realm, clients, Client, serverInfo, $route, Dialog, Notifications) {
$scope.realm = realm;
$scope.clients = clients;
- $scope.importButton = serverInfo.clientImporters.length > 0;
$scope.removeClient = function(client) {
Dialog.confirmDelete(client.clientId, 'client', function() {
@@ -670,7 +667,7 @@ module.controller('ClientInstallationCtrl', function($scope, realm, client, Clie
}
});
-module.controller('ClientDetailCtrl', function($scope, realm, client, $route, serverInfo, Client, $location, Dialog, Notifications) {
+module.controller('ClientDetailCtrl', function($scope, realm, client, $route, serverInfo, Client, ClientDescriptionConverter, $location, $modal, Dialog, Notifications) {
$scope.accessTypes = [
"confidential",
"public",
@@ -709,40 +706,45 @@ module.controller('ClientDetailCtrl', function($scope, realm, client, $route, se
$scope.samlEncrypt = false;
$scope.samlForcePostBinding = false;
$scope.samlForceNameIdFormat = false;
- if (!$scope.create) {
- if (!client.attributes) {
- client.attributes = {};
+
+ function updateProperties() {
+ if (!$scope.client.attributes) {
+ $scope.client.attributes = {};
}
- $scope.client= angular.copy(client);
$scope.accessType = $scope.accessTypes[0];
- if (client.bearerOnly) {
+ if ($scope.client.bearerOnly) {
$scope.accessType = $scope.accessTypes[2];
- } else if (client.publicClient) {
+ } else if ($scope.client.publicClient) {
$scope.accessType = $scope.accessTypes[1];
}
- if (client.protocol) {
- $scope.protocol = $scope.protocols[$scope.protocols.indexOf(client.protocol)];
+ if ($scope.client.protocol) {
+ $scope.protocol = $scope.protocols[$scope.protocols.indexOf($scope.client.protocol)];
} else {
$scope.protocol = $scope.protocols[0];
}
- if (client.attributes['saml.signature.algorithm'] == 'RSA_SHA1') {
+ if ($scope.client.attributes['saml.signature.algorithm'] == 'RSA_SHA1') {
$scope.signatureAlgorithm = $scope.signatureAlgorithms[0];
- } else if (client.attributes['saml.signature.algorithm'] == 'RSA_SHA256') {
+ } else if ($scope.client.attributes['saml.signature.algorithm'] == 'RSA_SHA256') {
$scope.signatureAlgorithm = $scope.signatureAlgorithms[1];
- } else if (client.attributes['saml.signature.algorithm'] == 'RSA_SHA512') {
+ } else if ($scope.client.attributes['saml.signature.algorithm'] == 'RSA_SHA512') {
$scope.signatureAlgorithm = $scope.signatureAlgorithms[2];
- } else if (client.attributes['saml.signature.algorithm'] == 'DSA_SHA1') {
+ } else if ($scope.client.attributes['saml.signature.algorithm'] == 'DSA_SHA1') {
$scope.signatureAlgorithm = $scope.signatureAlgorithms[3];
}
- if (client.attributes['saml_name_id_format'] == 'unspecified') {
+ if ($scope.client.attributes['saml_name_id_format'] == 'unspecified') {
$scope.nameIdFormat = $scope.nameIdFormats[0];
- } else if (client.attributes['saml_name_id_format'] == 'email') {
+ } else if ($scope.client.attributes['saml_name_id_format'] == 'email') {
$scope.nameIdFormat = $scope.nameIdFormats[1];
- } else if (client.attributes['saml_name_id_format'] == 'transient') {
+ } else if ($scope.client.attributes['saml_name_id_format'] == 'transient') {
$scope.nameIdFormat = $scope.nameIdFormats[2];
- } else if (client.attributes['saml_name_id_format'] == 'persistent') {
+ } else if ($scope.client.attributes['saml_name_id_format'] == 'persistent') {
$scope.nameIdFormat = $scope.nameIdFormats[3];
}
+ }
+
+ if (!$scope.create) {
+ $scope.client = angular.copy(client);
+ updateProperties();
} else {
$scope.client = { enabled: true, attributes: {}};
$scope.client.attributes['saml_signature_canonicalization_method'] = $scope.canonicalization[0].value;
@@ -813,6 +815,29 @@ module.controller('ClientDetailCtrl', function($scope, realm, client, $route, se
}
}
+ $scope.importFile = function(fileContent){
+ console.debug(fileContent);
+ ClientDescriptionConverter.save({
+ realm: realm.realm
+ }, fileContent, function (data) {
+ $scope.client = data;
+ updateProperties();
+ $scope.importing = true;
+ });
+ };
+
+ $scope.viewImportDetails = function() {
+ $modal.open({
+ templateUrl: resourceUrl + '/partials/modal/view-object.html',
+ controller: 'JsonModalCtrl',
+ resolve: {
+ object: function () {
+ return $scope.client;
+ }
+ }
+ })
+ };
+
$scope.switchChange = function() {
$scope.changed = true;
}
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
index d1abe26..8d56c90 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
@@ -927,6 +927,13 @@ module.factory('Client', function($resource) {
});
});
+module.factory('ClientDescriptionConverter', function($resource) {
+ return $resource(authUrl + '/admin/realms/:realm/client-description-converter', {
+ realm : '@realm'
+ });
+});
+
+
module.factory('ClientInstallation', function($resource) {
var url = authUrl + '/admin/realms/:realm/clients/:client/installation/json';
return {
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
index 06c939b..cc4ea82 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
@@ -10,6 +10,20 @@
<form class="form-horizontal" name="clientForm" novalidate kc-read-only="!access.manageClients">
<fieldset class="border-top">
+ <div class="form-group" data-ng-show="create">
+ <label for="name" class="col-sm-2 control-label">Import</label>
+
+ <div class="col-md-6" data-ng-hide="importing">
+ <label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
+ <input id="import-file" type="file" class="hidden" kc-on-read-file="importFile($fileContent)">
+ </div>
+
+ <div class="col-md-6" data-ng-show="importing">
+ <button class="btn btn-default" data-ng-click="viewImportDetails()">View details</button>
+ <button class="btn btn-default" data-ng-click="reset()">Clear import</button>
+ </div>
+ </div>
+
<div class="form-group">
<label class="col-md-2 control-label" for="clientId">Client ID <span class="required" data-ng-show="create">*</span></label>
<div class="col-sm-6">
@@ -174,6 +188,14 @@
<kc-tooltip>The name ID format to use for the subject.</kc-tooltip>
</div>
+ <div class="form-group" data-ng-show="!client.bearerOnly">
+ <label class="col-md-2 control-label" for="rootUrl">Root URL</label>
+ <div class="col-sm-6">
+ <input class="form-control" type="text" name="rootUrl" id="rootUrl" data-ng-model="client.rootUrl">
+ </div>
+ <kc-tooltip>Root URL appended to relative URLs</kc-tooltip>
+ </div>
+
<div class="form-group clearfix block" data-ng-hide="client.bearerOnly || client.directGrantsOnly">
<label class="col-md-2 control-label" for="newRedirectUri"><span class="required" data-ng-show="protocol != 'saml'">*</span> Valid Redirect URIs</label>
@@ -252,7 +274,7 @@
</div>
</div>
- <kc-tooltip>Allowed CORS origins.</kc-tooltip>
+ <kc-tooltip>Allowed CORS origins. To permit all origins of Valid Redirect URIs add '+'. To permit all origins add '*'.</kc-tooltip>
</div>
</fieldset>
<fieldset data-ng-show="protocol == 'saml'">
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-list.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
index 1b194bb..dfa3e00 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
@@ -37,7 +37,7 @@
<td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></td>
<td>{{client.enabled}}</td>
<td ng-class="{'text-muted': !client.baseUrl}">
- <a href="{{client.baseUrl}}" target="_blank" data-ng-show="client.baseUrl">{{client.baseUrl}}</a>
+ <a href="{{client.rootUrl}}{{client.baseUrl}}" target="_blank" data-ng-show="client.baseUrl">{{client.rootUrl}}{{client.baseUrl}}</a>
<span data-ng-hide="client.baseUrl">Not defined</span>
</td>
<td class="kc-action-cell">
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-create.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-create.html
index 4ac36fd..6de9285 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-create.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-create.html
@@ -1,8 +1,9 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+ <h1>Add Realm</h1>
+
<form class="form-horizontal" name="realmForm" novalidate>
<fieldset>
- <legend><span class="text">Create Realm</span></legend>
<div class="form-group">
<label for="name" class="col-sm-2 control-label">Import</label>
diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java
index 1de1c7e..89e896c 100755
--- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java
+++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java
@@ -241,7 +241,7 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
}
if (client != null) {
- attributes.put("client", new ClientBean(client));
+ attributes.put("client", new ClientBean(client, baseUri));
}
attributes.put("login", new LoginBean(formData));
@@ -322,7 +322,7 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
logger.warn("Failed to load properties", e);
}
if (client != null) {
- attributes.put("client", new ClientBean(client));
+ attributes.put("client", new ClientBean(client, baseUri));
}
Properties messagesBundle;
diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java
index 0404ea7..f10d031 100755
--- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java
+++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java
@@ -1,6 +1,9 @@
package org.keycloak.login.freemarker.model;
import org.keycloak.models.ClientModel;
+import org.keycloak.services.util.ResolveRelative;
+
+import java.net.URI;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -10,8 +13,11 @@ public class ClientBean {
protected ClientModel client;
- public ClientBean(ClientModel client) {
+ private URI requestUri;
+
+ public ClientBean(ClientModel client, URI requestUri) {
this.client = client;
+ this.requestUri = requestUri;
}
public String getClientId() {
@@ -23,7 +29,7 @@ public class ClientBean {
}
public String getBaseUrl() {
- return client.getBaseUrl();
+ return ResolveRelative.resolveRelativeUri(requestUri, client.getRootUrl(), client.getBaseUrl());
}
}
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java
index ad5315b..87513ec 100644
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java
@@ -1,13 +1,9 @@
package org.keycloak.admin.client.resource;
+import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
+import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.List;
import java.util.Map;
@@ -28,6 +24,12 @@ public interface RealmResource {
@Path("clients")
ClientsResource clients();
+ @Path("client-description-converter")
+ @POST
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN })
+ @Produces(MediaType.APPLICATION_JSON)
+ ClientRepresentation convertClientDescription(String description);
+
@Path("users")
UsersResource users();
diff --git a/model/api/src/main/java/org/keycloak/models/ClientModel.java b/model/api/src/main/java/org/keycloak/models/ClientModel.java
index daccf8e..ee4317c 100755
--- a/model/api/src/main/java/org/keycloak/models/ClientModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ClientModel.java
@@ -56,6 +56,10 @@ public interface ClientModel extends RoleContainerModel {
void setManagementUrl(String url);
+ String getRootUrl();
+
+ void setRootUrl(String url);
+
String getBaseUrl();
void setBaseUrl(String url);
diff --git a/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java b/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
index 52e9721..4c742ab 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
@@ -24,6 +24,7 @@ public class ClientEntity extends AbstractIdentifiableEntity {
private boolean surrogateAuthRequired;
private String managementUrl;
+ private String rootUrl;
private String baseUrl;
private boolean bearerOnly;
private boolean consentRequired;
@@ -196,6 +197,14 @@ public class ClientEntity extends AbstractIdentifiableEntity {
this.managementUrl = managementUrl;
}
+ public String getRootUrl() {
+ return rootUrl;
+ }
+
+ public void setRootUrl(String rootUrl) {
+ this.rootUrl = rootUrl;
+ }
+
public String getBaseUrl() {
return baseUrl;
}
diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index b71fce9..9906ab2 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -306,6 +306,7 @@ public class ModelToRepresentation {
rep.setServiceAccountsEnabled(clientModel.isServiceAccountsEnabled());
rep.setDirectGrantsOnly(clientModel.isDirectGrantsOnly());
rep.setSurrogateAuthRequired(clientModel.isSurrogateAuthRequired());
+ rep.setRootUrl(clientModel.getRootUrl());
rep.setBaseUrl(clientModel.getBaseUrl());
rep.setNotBefore(clientModel.getNotBefore());
rep.setNodeReRegistrationTimeout(clientModel.getNodeReRegistrationTimeout());
diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 8a79f01..ffb9673 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -692,6 +692,7 @@ public class RepresentationToModel {
client.setManagementUrl(resourceRep.getAdminUrl());
if (resourceRep.isSurrogateAuthRequired() != null)
client.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
+ if (resourceRep.getRootUrl() != null) client.setRootUrl(resourceRep.getRootUrl());
if (resourceRep.getBaseUrl() != null) client.setBaseUrl(resourceRep.getBaseUrl());
if (resourceRep.isBearerOnly() != null) client.setBearerOnly(resourceRep.isBearerOnly());
if (resourceRep.isConsentRequired() != null) client.setConsentRequired(resourceRep.isConsentRequired());
@@ -796,6 +797,7 @@ public class RepresentationToModel {
if (rep.isPublicClient() != null) resource.setPublicClient(rep.isPublicClient());
if (rep.isFullScopeAllowed() != null) resource.setFullScopeAllowed(rep.isFullScopeAllowed());
if (rep.isFrontchannelLogout() != null) resource.setFrontchannelLogout(rep.isFrontchannelLogout());
+ if (rep.getRootUrl() != null) resource.setRootUrl(rep.getRootUrl());
if (rep.getAdminUrl() != null) resource.setManagementUrl(rep.getAdminUrl());
if (rep.getBaseUrl() != null) resource.setBaseUrl(rep.getBaseUrl());
if (rep.isSurrogateAuthRequired() != null) resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired());
diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java
index 8003b70..1ddc364 100755
--- a/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java
+++ b/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java
@@ -422,6 +422,16 @@ public class ClientAdapter implements ClientModel {
}
@Override
+ public void setRootUrl(String url) {
+ entity.setRootUrl(url);
+ }
+
+ @Override
+ public String getRootUrl() {
+ return entity.getRootUrl();
+ }
+
+ @Override
public void setBaseUrl(String url) {
entity.setBaseUrl(url);
}
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java
index 9f79b15..e181978 100755
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java
@@ -346,6 +346,18 @@ public class ClientAdapter implements ClientModel {
}
@Override
+ public String getRootUrl() {
+ if (updated != null) return updated.getRootUrl();
+ return cached.getRootUrl();
+ }
+
+ @Override
+ public void setRootUrl(String url) {
+ getDelegateForUpdate();
+ updated.setRootUrl(url);
+ }
+
+ @Override
public String getBaseUrl() {
if (updated != null) return updated.getBaseUrl();
return cached.getBaseUrl();
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java
index 11447d0..3015acf 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java
@@ -42,6 +42,7 @@ public class CachedClient implements Serializable {
private Set<ProtocolMapperModel> protocolMappers = new HashSet<ProtocolMapperModel>();
private boolean surrogateAuthRequired;
private String managementUrl;
+ private String rootUrl;
private String baseUrl;
private List<String> defaultRoles = new LinkedList<String>();
private boolean bearerOnly;
@@ -76,6 +77,7 @@ public class CachedClient implements Serializable {
}
surrogateAuthRequired = model.isSurrogateAuthRequired();
managementUrl = model.getManagementUrl();
+ rootUrl = model.getRootUrl();
baseUrl = model.getBaseUrl();
defaultRoles.addAll(model.getDefaultRoles());
bearerOnly = model.isBearerOnly();
@@ -169,6 +171,10 @@ public class CachedClient implements Serializable {
return managementUrl;
}
+ public String getRootUrl() {
+ return rootUrl;
+ }
+
public String getBaseUrl() {
return baseUrl;
}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
index b0acc41..1e0c21e 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
@@ -442,6 +442,16 @@ public class ClientAdapter implements ClientModel {
}
@Override
+ public String getRootUrl() {
+ return entity.getRootUrl();
+ }
+
+ @Override
+ public void setRootUrl(String url) {
+ entity.setRootUrl(url);
+ }
+
+ @Override
public String getBaseUrl() {
return entity.getBaseUrl();
}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
index 1f6ac25..b0a30cd 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
@@ -82,6 +82,9 @@ public class ClientEntity {
@Column(name="SURROGATE_AUTH_REQUIRED")
private boolean surrogateAuthRequired;
+ @Column(name="ROOT_URL")
+ private String rootUrl;
+
@Column(name="BASE_URL")
private String baseUrl;
@@ -260,6 +263,14 @@ public class ClientEntity {
this.surrogateAuthRequired = surrogateAuthRequired;
}
+ public String getRootUrl() {
+ return rootUrl;
+ }
+
+ public void setRootUrl(String rootUrl) {
+ this.rootUrl = rootUrl;
+ }
+
public String getBaseUrl() {
return baseUrl;
}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
index 26effca..4e1b4fa 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
@@ -440,6 +440,17 @@ public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> imple
}
@Override
+ public void setRootUrl(String url) {
+ getMongoEntity().setRootUrl(url);
+ updateMongoEntity();
+ }
+
+ @Override
+ public String getRootUrl() {
+ return getMongoEntity().getRootUrl();
+ }
+
+ @Override
public void setBaseUrl(String url) {
getMongoEntity().setBaseUrl(url);
updateMongoEntity();
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
index d6b745b..8d6fa15 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
@@ -485,7 +485,7 @@ public class SamlProtocol implements LoginProtocol {
}
if (logoutServiceUrl == null && client instanceof ClientModel) logoutServiceUrl = ((ClientModel)client).getManagementUrl();
if (logoutServiceUrl == null || logoutServiceUrl.trim().equals("")) return null;
- return ResourceAdminManager.resolveUri(uriInfo.getRequestUri(), logoutServiceUrl);
+ return ResourceAdminManager.resolveUri(uriInfo.getRequestUri(), client.getRootUrl(), logoutServiceUrl);
}
diff --git a/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.exportimport.ClientDescriptionConverterFactory b/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.exportimport.ClientDescriptionConverterFactory
new file mode 100755
index 0000000..b874ead
--- /dev/null
+++ b/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.exportimport.ClientDescriptionConverterFactory
@@ -0,0 +1 @@
+org.keycloak.protocol.saml.EntityDescriptorDescriptionConverter
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java
index 156ee44..17c3bdb 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java
@@ -58,7 +58,7 @@ public class LoginStatusIframeEndpoint {
}
}
- for (String r : RedirectUtils.resolveValidRedirects(uriInfo, client.getRedirectUris())) {
+ for (String r : RedirectUtils.resolveValidRedirects(uriInfo, client.getRootUrl(), client.getRedirectUris())) {
int i = r.indexOf('/', 8);
if (i != -1) {
r = r.substring(0, i);
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCClientDescriptionConverter.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCClientDescriptionConverter.java
new file mode 100644
index 0000000..56b47bb
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCClientDescriptionConverter.java
@@ -0,0 +1,65 @@
+package org.keycloak.protocol.oidc;
+
+import org.keycloak.Config;
+import org.keycloak.exportimport.ClientDescriptionConverter;
+import org.keycloak.exportimport.ClientDescriptionConverterFactory;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.protocol.oidc.representations.OIDCClientRepresentation;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.util.JsonSerialization;
+
+import java.io.IOException;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class OIDCClientDescriptionConverter implements ClientDescriptionConverter, ClientDescriptionConverterFactory {
+
+ @Override
+ public boolean isSupported(String description) {
+ description = description.trim();
+ return (description.startsWith("{") && description.endsWith("}") && description.contains("\"redirect_uris\""));
+ }
+
+ @Override
+ public ClientRepresentation convertToInternal(String description) {
+ try {
+ OIDCClientRepresentation oidcRep = JsonSerialization.readValue(description, OIDCClientRepresentation.class);
+
+ ClientRepresentation client = new ClientRepresentation();
+ client.setClientId(KeycloakModelUtils.generateId());
+ client.setName(oidcRep.getClientName());
+ client.setRedirectUris(oidcRep.getRedirectUris());
+ client.setBaseUrl(oidcRep.getClientUri());
+
+ return client;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public ClientDescriptionConverter create(KeycloakSession session) {
+ return this;
+ }
+
+ @Override
+ public void init(Config.Scope config) {
+ }
+
+ @Override
+ public void postInit(KeycloakSessionFactory factory) {
+ }
+
+ @Override
+ public void close() {
+ }
+
+ @Override
+ public String getId() {
+ return "openid-connect";
+ }
+
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/representations/OIDCClientRepresentation.java b/services/src/main/java/org/keycloak/protocol/oidc/representations/OIDCClientRepresentation.java
new file mode 100644
index 0000000..7de415c
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/representations/OIDCClientRepresentation.java
@@ -0,0 +1,45 @@
+package org.keycloak.protocol.oidc.representations;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class OIDCClientRepresentation {
+
+ @JsonProperty("redirect_uris")
+ private List<String> redirectUris;
+
+ @JsonProperty("client_name")
+ private String clientName;
+
+ @JsonProperty("client_uri")
+ private String clientUri;
+
+ public List<String> getRedirectUris() {
+ return redirectUris;
+ }
+
+ public void setRedirectUris(List<String> redirectUris) {
+ this.redirectUris = redirectUris;
+ }
+
+ public String getClientName() {
+ return clientName;
+ }
+
+ public void setClientName(String clientName) {
+ this.clientName = clientName;
+ }
+
+ public String getClientUri() {
+ return clientUri;
+ }
+
+ public void setClientUri(String clientUri) {
+ this.clientUri = clientUri;
+ }
+
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
index c43140a..c166565 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
@@ -24,6 +24,7 @@ import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.ProtocolMapper;
import org.keycloak.protocol.oidc.mappers.OIDCAccessTokenMapper;
import org.keycloak.protocol.oidc.mappers.OIDCIDTokenMapper;
+import org.keycloak.protocol.oidc.utils.WebOriginsUtils;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.IDToken;
@@ -217,7 +218,7 @@ public class TokenManager {
}
public AccessToken createClientAccessToken(KeycloakSession session, Set<RoleModel> requestedRoles, RealmModel realm, ClientModel client, UserModel user, UserSessionModel userSession, ClientSessionModel clientSession) {
- AccessToken token = initToken(realm, client, user, userSession, clientSession);
+ AccessToken token = initToken(realm, client, user, userSession, clientSession, session.getContext().getUri());
for (RoleModel role : requestedRoles) {
addComposites(token, role);
}
@@ -380,7 +381,7 @@ public class TokenManager {
}
- protected AccessToken initToken(RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, ClientSessionModel clientSession) {
+ protected AccessToken initToken(RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, ClientSessionModel clientSession, UriInfo uriInfo) {
AccessToken token = new AccessToken();
if (clientSession != null) token.clientSession(clientSession.getId());
token.id(KeycloakModelUtils.generateId());
@@ -398,7 +399,7 @@ public class TokenManager {
}
Set<String> allowedOrigins = client.getWebOrigins();
if (allowedOrigins != null) {
- token.setAllowedOrigins(allowedOrigins);
+ token.setAllowedOrigins(WebOriginsUtils.resolveValidWebOrigins(uriInfo, client));
}
return token;
}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
index df650f6..ff4601f 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
@@ -19,22 +19,22 @@ public class RedirectUtils {
private static final Logger logger = Logger.getLogger(RedirectUtils.class);
public static String verifyRealmRedirectUri(UriInfo uriInfo, String redirectUri, RealmModel realm) {
- Set<String> validRedirects = getValidateRedirectUris(realm);
- return verifyRedirectUri(uriInfo, redirectUri, realm, validRedirects);
+ Set<String> validRedirects = getValidateRedirectUris(uriInfo, realm);
+ return verifyRedirectUri(uriInfo, null, redirectUri, realm, validRedirects);
}
public static String verifyRedirectUri(UriInfo uriInfo, String redirectUri, RealmModel realm, ClientModel client) {
Set<String> validRedirects = client.getRedirectUris();
- return verifyRedirectUri(uriInfo, redirectUri, realm, validRedirects);
+ return verifyRedirectUri(uriInfo, client.getRootUrl(), redirectUri, realm, validRedirects);
}
- public static Set<String> resolveValidRedirects(UriInfo uriInfo, Set<String> validRedirects) {
+ public static Set<String> resolveValidRedirects(UriInfo uriInfo, String rootUrl, Set<String> validRedirects) {
// If the valid redirect URI is relative (no scheme, host, port) then use the request's scheme, host, and port
Set<String> resolveValidRedirects = new HashSet<String>();
for (String validRedirect : validRedirects) {
resolveValidRedirects.add(validRedirect); // add even relative urls.
if (validRedirect.startsWith("/")) {
- validRedirect = relativeToAbsoluteURI(uriInfo, validRedirect);
+ validRedirect = relativeToAbsoluteURI(uriInfo, rootUrl, validRedirect);
logger.debugv("replacing relative valid redirect with: {0}", validRedirect);
resolveValidRedirects.add(validRedirect);
}
@@ -42,17 +42,15 @@ public class RedirectUtils {
return resolveValidRedirects;
}
- private static Set<String> getValidateRedirectUris(RealmModel realm) {
- Set<String> redirects = new HashSet<String>();
+ private static Set<String> getValidateRedirectUris(UriInfo uriInfo, RealmModel realm) {
+ Set<String> redirects = new HashSet<>();
for (ClientModel client : realm.getClients()) {
- for (String redirect : client.getRedirectUris()) {
- redirects.add(redirect);
- }
+ redirects.addAll(resolveValidRedirects(uriInfo, client.getRootUrl(), client.getRedirectUris()));
}
return redirects;
}
- private static String verifyRedirectUri(UriInfo uriInfo, String redirectUri, RealmModel realm, Set<String> validRedirects) {
+ private static String verifyRedirectUri(UriInfo uriInfo, String rootUrl, String redirectUri, RealmModel realm, Set<String> validRedirects) {
if (redirectUri == null) {
if (validRedirects.size() != 1) return null;
String validRedirect = validRedirects.iterator().next();
@@ -66,7 +64,7 @@ public class RedirectUtils {
redirectUri = null;
} else {
String r = redirectUri.indexOf('?') != -1 ? redirectUri.substring(0, redirectUri.indexOf('?')) : redirectUri;
- Set<String> resolveValidRedirects = resolveValidRedirects(uriInfo, validRedirects);
+ Set<String> resolveValidRedirects = resolveValidRedirects(uriInfo, rootUrl, validRedirects);
boolean valid = matchesRedirects(resolveValidRedirects, r);
@@ -86,7 +84,7 @@ public class RedirectUtils {
valid = matchesRedirects(resolveValidRedirects, r);
}
if (valid && redirectUri.startsWith("/")) {
- redirectUri = relativeToAbsoluteURI(uriInfo, redirectUri);
+ redirectUri = relativeToAbsoluteURI(uriInfo, rootUrl, redirectUri);
}
redirectUri = valid ? redirectUri : null;
}
@@ -98,13 +96,16 @@ public class RedirectUtils {
}
}
- private static String relativeToAbsoluteURI(UriInfo uriInfo, String relative) {
- URI baseUri = uriInfo.getBaseUri();
- String uri = baseUri.getScheme() + "://" + baseUri.getHost();
- if (baseUri.getPort() != -1) {
- uri += ":" + baseUri.getPort();
+ private static String relativeToAbsoluteURI(UriInfo uriInfo, String rootUrl, String relative) {
+ if (rootUrl == null) {
+ URI baseUri = uriInfo.getBaseUri();
+ String uri = baseUri.getScheme() + "://" + baseUri.getHost();
+ if (baseUri.getPort() != -1) {
+ uri += ":" + baseUri.getPort();
+ }
+ rootUrl = uri;
}
- relative = uri + relative;
+ relative = rootUrl + relative;
return relative;
}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/WebOriginsUtils.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/WebOriginsUtils.java
new file mode 100644
index 0000000..5684ef6
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/WebOriginsUtils.java
@@ -0,0 +1,30 @@
+package org.keycloak.protocol.oidc.utils;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.util.UriUtils;
+
+import javax.ws.rs.core.UriInfo;
+import java.util.Set;
+
+/**
+ * Created by st on 22.09.15.
+ */
+public class WebOriginsUtils {
+
+ public static final String INCLUDE_REDIRECTS = "+";
+
+ public static Set<String> resolveValidWebOrigins(UriInfo uriInfo, ClientModel client) {
+ Set<String> webOrigins = client.getWebOrigins();
+ if (webOrigins != null && webOrigins.contains("+")) {
+ webOrigins.remove(INCLUDE_REDIRECTS);
+ client.getRedirectUris();
+ for (String redirectUri : RedirectUtils.resolveValidRedirects(uriInfo, client.getRootUrl(), client.getRedirectUris())) {
+ if (redirectUri.startsWith("http://") || redirectUri.startsWith("https://")) {
+ webOrigins.add(UriUtils.getOrigin(redirectUri));
+ }
+ }
+ }
+ return webOrigins;
+ }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
index 8a94b6e..d2014d5 100755
--- a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
@@ -46,8 +46,8 @@ public class ResourceAdminManager {
this.session = session;
}
- public static String resolveUri(URI requestUri, String uri) {
- String absoluteURI = ResolveRelative.resolveRelativeUri(requestUri, uri);
+ public static String resolveUri(URI requestUri, String rootUrl, String uri) {
+ String absoluteURI = ResolveRelative.resolveRelativeUri(requestUri, rootUrl, uri);
return StringPropertyReplacer.replaceProperties(absoluteURI);
}
@@ -58,8 +58,7 @@ public class ResourceAdminManager {
return null;
}
- // this is to support relative admin urls when keycloak and clients are deployed on the same machine
- String absoluteURI = ResolveRelative.resolveRelativeUri(requestUri, mgmtUrl);
+ String absoluteURI = ResolveRelative.resolveRelativeUri(requestUri, client.getRootUrl(), mgmtUrl);
// this is for resolving URI like "http://${jboss.host.name}:8080/..." in order to send request to same machine and avoid request to LB in cluster environment
return StringPropertyReplacer.replaceProperties(absoluteURI);
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index 3b6edea..20e7b6e 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -779,7 +779,7 @@ public class AccountService extends AbstractSecuredLocalService {
if (referrerUri != null) {
referrerUri = RedirectUtils.verifyRedirectUri(uriInfo, referrerUri, realm, referrerClient);
} else {
- referrerUri = ResolveRelative.resolveRelativeUri(uriInfo.getRequestUri(), referrerClient.getBaseUrl());
+ referrerUri = ResolveRelative.resolveRelativeUri(uriInfo.getRequestUri(), client.getRootUrl(), referrerClient.getBaseUrl());
}
if (referrerUri != null) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
index 70022c0..4ef2a63 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
@@ -4,8 +4,6 @@ import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.broker.provider.IdentityProviderFactory;
import org.keycloak.events.EventType;
import org.keycloak.events.admin.OperationType;
-import org.keycloak.exportimport.ClientImporter;
-import org.keycloak.exportimport.ClientImporterFactory;
import org.keycloak.freemarker.Theme;
import org.keycloak.freemarker.ThemeProvider;
import org.keycloak.models.KeycloakSession;
@@ -51,7 +49,6 @@ public class ServerInfoAdminResource {
setSocialProviders(info);
setIdentityProviders(info);
setThemes(info);
- setClientImporters(info);
setProviders(info);
setProtocolMapperTypes(info);
setBuiltinProtocolMappers(info);
@@ -144,7 +141,7 @@ public class ServerInfoAdminResource {
ProtocolMapper mapper = (ProtocolMapper)p;
List<ProtocolMapperTypeRepresentation> types = info.getProtocolMapperTypes().get(mapper.getProtocol());
if (types == null) {
- types = new LinkedList<ProtocolMapperTypeRepresentation>();
+ types = new LinkedList<>();
info.getProtocolMapperTypes().put(mapper.getProtocol(), types);
}
ProtocolMapperTypeRepresentation rep = new ProtocolMapperTypeRepresentation();
@@ -179,17 +176,6 @@ public class ServerInfoAdminResource {
}
}
- private void setClientImporters(ServerInfoRepresentation info) {
- info.setClientImporters(new LinkedList<Map<String, String>>());
- for (ProviderFactory p : session.getKeycloakSessionFactory().getProviderFactories(ClientImporter.class)) {
- ClientImporterFactory factory = (ClientImporterFactory)p;
- Map<String, String> data = new HashMap<String, String>();
- data.put("id", factory.getId());
- data.put("name", factory.getDisplayName());
- info.getClientImporters().add(data);
- }
- }
-
private static Map<String, List<String>> createEnumsMap(Class... enums) {
Map<String, List<String>> m = new HashMap<>();
for (Class e : enums) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index fda0ee3..82dc0bd 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -13,7 +13,8 @@ import org.keycloak.events.EventType;
import org.keycloak.events.admin.AdminEvent;
import org.keycloak.events.admin.AdminEventQuery;
import org.keycloak.events.admin.OperationType;
-import org.keycloak.exportimport.ClientImporter;
+import org.keycloak.exportimport.ClientDescriptionConverter;
+import org.keycloak.exportimport.ClientDescriptionConverterFactory;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
@@ -25,7 +26,9 @@ import org.keycloak.models.cache.CacheUserProvider;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.protocol.oidc.TokenManager;
+import org.keycloak.provider.ProviderFactory;
import org.keycloak.representations.adapters.action.GlobalRequestResult;
+import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.AuthenticationManager;
@@ -99,10 +102,18 @@ public class RealmAdminResource {
*
* @return
*/
- @Path("client-importers/{formatId}")
- public Object getClientImporter(@PathParam("formatId") String formatId) {
- ClientImporter importer = session.getProvider(ClientImporter.class, formatId);
- return importer.createJaxrsService(realm, auth);
+ @Path("client-description-converter")
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN })
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ public ClientRepresentation convertClientDescription(String description) {
+ for (ProviderFactory<ClientDescriptionConverter> factory : session.getKeycloakSessionFactory().getProviderFactories(ClientDescriptionConverter.class)) {
+ if (((ClientDescriptionConverterFactory) factory).isSupported(description)) {
+ return factory.create(session).convertToInternal(description);
+ }
+ }
+
+ throw new BadRequestException("Unsupported format");
}
/**
diff --git a/services/src/main/java/org/keycloak/services/resources/ClientRegistrationService.java b/services/src/main/java/org/keycloak/services/resources/ClientRegistrationService.java
new file mode 100644
index 0000000..87e55b8
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/ClientRegistrationService.java
@@ -0,0 +1,100 @@
+package org.keycloak.services.resources;
+
+import org.jboss.logging.Logger;
+import org.jboss.resteasy.spi.BadRequestException;
+import org.jboss.resteasy.spi.NotFoundException;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.exportimport.ClientDescriptionConverter;
+import org.keycloak.exportimport.KeycloakClientDescriptionConverter;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.models.utils.RepresentationToModel;
+import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.services.ErrorResponse;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.net.URI;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ClientRegistrationService {
+
+ protected static final Logger logger = Logger.getLogger(ClientRegistrationService.class);
+
+ private RealmModel realm;
+
+ private EventBuilder event;
+
+ @Context
+ private KeycloakSession session;
+
+ public ClientRegistrationService(RealmModel realm, EventBuilder event) {
+ this.realm = realm;
+ this.event = event;
+ }
+
+ @POST
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN })
+ public Response create(String description, @QueryParam("format") String format) {
+ if (format == null) {
+ format = KeycloakClientDescriptionConverter.ID;
+ }
+
+ ClientDescriptionConverter converter = session.getProvider(ClientDescriptionConverter.class, format);
+ if (converter == null) {
+ throw new BadRequestException("Invalid format");
+ }
+ ClientRepresentation rep = converter.convertToInternal(description);
+
+ try {
+ ClientModel clientModel = RepresentationToModel.createClient(session, realm, rep, true);
+ rep = ModelToRepresentation.toRepresentation(clientModel);
+ URI uri = session.getContext().getUri().getAbsolutePathBuilder().path(clientModel.getId()).build();
+ return Response.created(uri).entity(rep).build();
+ } catch (ModelDuplicateException e) {
+ return ErrorResponse.exists("Client " + rep.getClientId() + " already exists");
+ }
+ }
+
+ @GET
+ @Path("{clientId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public ClientRepresentation get(@PathParam("clientId") String clientId) {
+ AuthorizeClientUtil.ClientAuthResult clientAuth = AuthorizeClientUtil.authorizeClient(session, event, realm);
+ ClientModel client = clientAuth.getClient();
+ if (client == null) {
+ throw new NotFoundException("Client not found");
+ }
+ return ModelToRepresentation.toRepresentation(client);
+ }
+
+ @PUT
+ @Path("{clientId}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ public void update(@PathParam("clientId") String clientId, ClientRepresentation rep) {
+ ClientModel client = realm.getClientByClientId(clientId);
+ if (client == null) {
+ throw new NotFoundException("Client not found");
+ }
+ RepresentationToModel.updateClient(rep, client);
+ }
+
+ @DELETE
+ @Path("{clientId}")
+ public void delete(@PathParam("clientId") String clientId) {
+ ClientModel client = realm.getClientByClientId(clientId);
+ if (client == null) {
+ throw new NotFoundException("Client not found");
+ }
+ realm.removeClient(client.getId());
+ }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
index 083eb9a..52f49df 100755
--- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
@@ -112,6 +112,15 @@ public class RealmsResource {
return service;
}
+// @Path("{realm}/client-registration")
+// public ClientRegistrationService getClientsService(final @PathParam("realm") String name) {
+// RealmModel realm = init(name);
+// EventBuilder event = new EventBuilder(realm, session, clientConnection);
+// ClientRegistrationService service = new ClientRegistrationService(realm, event);
+// ResteasyProviderFactory.getInstance().injectProperties(service);
+// return service;
+// }
+
@Path("{realm}/clients-managements")
public ClientsManagementService getClientsManagementService(final @PathParam("realm") String name) {
RealmModel realm = init(name);
diff --git a/services/src/main/java/org/keycloak/services/util/ResolveRelative.java b/services/src/main/java/org/keycloak/services/util/ResolveRelative.java
index 0954f73..757ff58 100755
--- a/services/src/main/java/org/keycloak/services/util/ResolveRelative.java
+++ b/services/src/main/java/org/keycloak/services/util/ResolveRelative.java
@@ -8,13 +8,17 @@ import java.net.URI;
* @version $Revision: 1 $
*/
public class ResolveRelative {
- public static String resolveRelativeUri(URI requestUri, String url) {
+ public static String resolveRelativeUri(URI requestUri, String rootUrl, String url) {
if (url == null || !url.startsWith("/")) return url;
- UriBuilder builder = UriBuilder.fromPath(url).host(requestUri.getHost());
- builder.scheme(requestUri.getScheme());
- if (requestUri.getPort() != -1) {
- builder.port(requestUri.getPort());
+ if (rootUrl != null) {
+ return rootUrl + url;
+ } else {
+ UriBuilder builder = UriBuilder.fromPath(url).host(requestUri.getHost());
+ builder.scheme(requestUri.getScheme());
+ if (requestUri.getPort() != -1) {
+ builder.port(requestUri.getPort());
+ }
+ return builder.build().toString();
}
- return builder.build().toString();
}
}
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.exportimport.ClientDescriptionConverterFactory b/services/src/main/resources/META-INF/services/org.keycloak.exportimport.ClientDescriptionConverterFactory
new file mode 100644
index 0000000..139c7b1
--- /dev/null
+++ b/services/src/main/resources/META-INF/services/org.keycloak.exportimport.ClientDescriptionConverterFactory
@@ -0,0 +1,2 @@
+org.keycloak.exportimport.KeycloakClientDescriptionConverter
+org.keycloak.protocol.oidc.OIDCClientDescriptionConverter
\ No newline at end of file
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi
index 0a9b272..6d88f97 100755
--- a/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi
+++ b/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -1,6 +1,6 @@
org.keycloak.protocol.LoginProtocolSpi
org.keycloak.protocol.ProtocolMapperSpi
-org.keycloak.exportimport.ClientImportSpi
+org.keycloak.exportimport.ClientDescriptionConverterSpi
org.keycloak.wellknown.WellKnownSpi
org.keycloak.messages.MessagesSpi
org.keycloak.authentication.AuthenticatorSpi
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java
index aaed86e..deda8f8 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java
@@ -177,6 +177,7 @@ public class AdminAPITest {
if (appRep.isBearerOnly() != null) Assert.assertEquals(appRep.isBearerOnly(), storedApp.isBearerOnly());
if (appRep.isPublicClient() != null) Assert.assertEquals(appRep.isPublicClient(), storedApp.isPublicClient());
if (appRep.isFullScopeAllowed() != null) Assert.assertEquals(appRep.isFullScopeAllowed(), storedApp.isFullScopeAllowed());
+ if (appRep.getRootUrl() != null) Assert.assertEquals(appRep.getRootUrl(), storedApp.getRootUrl());
if (appRep.getAdminUrl() != null) Assert.assertEquals(appRep.getAdminUrl(), storedApp.getAdminUrl());
if (appRep.getBaseUrl() != null) Assert.assertEquals(appRep.getBaseUrl(), storedApp.getBaseUrl());
if (appRep.isSurrogateAuthRequired() != null) Assert.assertEquals(appRep.isSurrogateAuthRequired(), storedApp.isSurrogateAuthRequired());
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/RealmTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/RealmTest.java
index 8208aa2..8c41dfa 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/RealmTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/RealmTest.java
@@ -1,13 +1,18 @@
package org.keycloak.testsuite.admin;
+import org.apache.commons.io.IOUtils;
import org.junit.Test;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
+import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.services.managers.RealmManager;
+import org.keycloak.util.JsonSerialization;
import javax.ws.rs.NotFoundException;
+import java.io.IOException;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -132,4 +137,35 @@ public class RealmTest extends AbstractClientTest {
}
}
+ @Test
+ public void convertKeycloakClientDescription() throws IOException {
+ ClientRepresentation description = new ClientRepresentation();
+ description.setClientId("client-id");
+ description.setRedirectUris(Collections.singletonList("http://localhost"));
+
+ ClientRepresentation converted = realm.convertClientDescription(JsonSerialization.writeValueAsString(description));
+ assertEquals("client-id", converted.getClientId());
+ assertEquals("http://localhost", converted.getRedirectUris().get(0));
+ }
+
+ @Test
+ public void convertOIDCClientDescription() throws IOException {
+ String description = IOUtils.toString(getClass().getResourceAsStream("/client-descriptions/client-oidc.json"));
+
+ ClientRepresentation converted = realm.convertClientDescription(description);
+ assertEquals(36, converted.getClientId().length());
+ assertEquals(1, converted.getRedirectUris().size());
+ assertEquals("http://localhost", converted.getRedirectUris().get(0));
+ }
+
+ @Test
+ public void convertSAMLClientDescription() throws IOException {
+ String description = IOUtils.toString(getClass().getResourceAsStream("/client-descriptions/saml-entity-descriptor.xml"));
+
+ ClientRepresentation converted = realm.convertClientDescription(description);
+ assertEquals("loadbalancer-9.siroe.com", converted.getClientId());
+ assertEquals(1, converted.getRedirectUris().size());
+ assertEquals("https://LoadBalancer-9.siroe.com:3443/federation/Consumer/metaAlias/sp", converted.getRedirectUris().get(0));
+ }
+
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTest.java
index 358fd23..f97a05e 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTest.java
@@ -30,7 +30,7 @@ public class SamlAdapterTest {
initializeSamlSecuredWar("/keycloak-saml/bad-client-signed-post", "/bad-client-sales-post-sig", "bad-client-post-sig.war", classLoader);
initializeSamlSecuredWar("/keycloak-saml/bad-realm-signed-post", "/bad-realm-sales-post-sig", "bad-realm-post-sig.war", classLoader);
initializeSamlSecuredWar("/keycloak-saml/encrypted-post", "/sales-post-enc", "post-enc.war", classLoader);
- SamlAdapterTestStrategy.uploadSP("http://localhost:8081/auth", this);
+ SamlAdapterTestStrategy.uploadSP("http://localhost:8081/auth");
server.getServer().deploy(createDeploymentInfo("employee.war", "/employee", SamlSPFacade.class));
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTestStrategy.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTestStrategy.java
index 6e0817b..2c32d51 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTestStrategy.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTestStrategy.java
@@ -1,5 +1,6 @@
package org.keycloak.testsuite.keycloaksaml;
+import org.apache.commons.io.IOUtils;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;
import org.junit.Assert;
import org.junit.ClassRule;
@@ -8,6 +9,8 @@ import org.junit.Test;
import org.junit.rules.ExternalResource;
import org.keycloak.Config;
import org.keycloak.adapters.saml.SamlPrincipal;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.Constants;
@@ -24,6 +27,7 @@ import org.keycloak.protocol.saml.mappers.HardcodedRole;
import org.keycloak.protocol.saml.mappers.RoleListMapper;
import org.keycloak.protocol.saml.mappers.RoleNameMapper;
import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
import org.keycloak.services.managers.RealmManager;
@@ -34,6 +38,7 @@ import org.keycloak.testsuite.rule.AbstractKeycloakRule;
import org.keycloak.testsuite.rule.KeycloakRule;
import org.keycloak.testsuite.rule.WebResource;
import org.keycloak.testsuite.rule.WebRule;
+import org.keycloak.util.JsonSerialization;
import org.openqa.selenium.WebDriver;
import javax.ws.rs.client.Client;
@@ -51,6 +56,8 @@ import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
+import static org.junit.Assert.assertEquals;
+
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
@@ -106,9 +113,9 @@ public class SamlAdapterTestStrategy extends ExternalResource {
public void testPostSimpleLoginLogout() {
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post/");
- Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
loginPage.login("bburke", "password");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post/");
System.out.println(driver.getPageSource());
Assert.assertTrue(driver.getPageSource().contains("bburke"));
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post?GLO=true");
@@ -117,9 +124,9 @@ public class SamlAdapterTestStrategy extends ExternalResource {
public void testPostSimpleUnauthorized(CheckAuthError error) {
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post/");
- Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
loginPage.login("unauthorized", "password");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post/");
System.out.println(driver.getPageSource());
error.check(driver);
}
@@ -127,7 +134,7 @@ public class SamlAdapterTestStrategy extends ExternalResource {
public void testPostSimpleLoginLogoutIdpInitiated() {
driver.navigate().to(AUTH_SERVER_URL + "/realms/demo/protocol/saml/clients/sales-post");
loginPage.login("bburke", "password");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post/");
System.out.println(driver.getPageSource());
Assert.assertTrue(driver.getPageSource().contains("bburke"));
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post?GLO=true");
@@ -136,9 +143,9 @@ public class SamlAdapterTestStrategy extends ExternalResource {
public void testPostSignedLoginLogout() {
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig/");
- Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
loginPage.login("bburke", "password");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig/");
Assert.assertTrue(driver.getPageSource().contains("bburke"));
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig?GLO=true");
checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig/");
@@ -146,9 +153,9 @@ public class SamlAdapterTestStrategy extends ExternalResource {
}
public void testPostSignedLoginLogoutTransientNameID() {
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-transient/");
- Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
loginPage.login("bburke", "password");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig-transient/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig-transient/");
System.out.println(driver.getPageSource());
Assert.assertFalse(driver.getPageSource().contains("bburke"));
Assert.assertTrue(driver.getPageSource().contains("principal=G-"));
@@ -158,9 +165,9 @@ public class SamlAdapterTestStrategy extends ExternalResource {
}
public void testPostSignedLoginLogoutPersistentNameID() {
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-persistent/");
- Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
loginPage.login("bburke", "password");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig-persistent/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig-persistent/");
System.out.println(driver.getPageSource());
Assert.assertFalse(driver.getPageSource().contains("bburke"));
Assert.assertTrue(driver.getPageSource().contains("principal=G-"));
@@ -170,9 +177,9 @@ public class SamlAdapterTestStrategy extends ExternalResource {
}
public void testPostSignedLoginLogoutEmailNameID() {
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-email/");
- Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
loginPage.login("bburke", "password");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig-email/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig-email/");
System.out.println(driver.getPageSource());
Assert.assertTrue(driver.getPageSource().contains("principal=bburke@redhat.com"));
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-email?GLO=true");
@@ -188,8 +195,8 @@ public class SamlAdapterTestStrategy extends ExternalResource {
Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
System.out.println(driver.getCurrentUrl());
loginPage.login("bburke", "password");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee/");
- Assert.assertEquals(SamlSPFacade.sentRelayState, SamlSPFacade.RELAY_STATE);
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee/");
+ assertEquals(SamlSPFacade.sentRelayState, SamlSPFacade.RELAY_STATE);
Assert.assertNotNull(SamlSPFacade.samlResponse);
}
@@ -206,13 +213,13 @@ public class SamlAdapterTestStrategy extends ExternalResource {
requiredRoles.add("user");
SendUsernameServlet.checkRoles = requiredRoles;
loginPage.login("bburke", "password");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee2/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee2/");
SendUsernameServlet.checkRoles = null;
SamlPrincipal principal = (SamlPrincipal) SendUsernameServlet.sentPrincipal;
Assert.assertNotNull(principal);
- Assert.assertEquals("bburke@redhat.com", principal.getAttribute(X500SAMLProfileConstants.EMAIL.get()));
- Assert.assertEquals("bburke@redhat.com", principal.getFriendlyAttribute("email"));
- Assert.assertEquals("617", principal.getAttribute("phone"));
+ assertEquals("bburke@redhat.com", principal.getAttribute(X500SAMLProfileConstants.EMAIL.get()));
+ assertEquals("bburke@redhat.com", principal.getFriendlyAttribute("email"));
+ assertEquals("617", principal.getAttribute("phone"));
Assert.assertNull(principal.getFriendlyAttribute("phone"));
driver.navigate().to(APP_SERVER_BASE_URL + "/employee2/?GLO=true");
checkLoggedOut(APP_SERVER_BASE_URL + "/employee2/");
@@ -252,11 +259,11 @@ public class SamlAdapterTestStrategy extends ExternalResource {
requiredRoles.add("pee-on");
SendUsernameServlet.checkRoles = requiredRoles;
loginPage.login("bburke", "password");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee2/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee2/");
SendUsernameServlet.checkRoles = null;
SamlPrincipal principal = (SamlPrincipal) SendUsernameServlet.sentPrincipal;
Assert.assertNotNull(principal);
- Assert.assertEquals("hard", principal.getAttribute("hardcoded-attribute"));
+ assertEquals("hard", principal.getAttribute("hardcoded-attribute"));
}
@@ -266,7 +273,7 @@ public class SamlAdapterTestStrategy extends ExternalResource {
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig/");
Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
loginPage.login("bburke", "password");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee-sig/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee-sig/");
Assert.assertTrue(driver.getPageSource().contains("bburke"));
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig?GLO=true");
checkLoggedOut(APP_SERVER_BASE_URL + "/employee-sig/");
@@ -277,7 +284,7 @@ public class SamlAdapterTestStrategy extends ExternalResource {
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig-front/");
Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
loginPage.login("bburke", "password");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee-sig-front/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee-sig-front/");
Assert.assertTrue(driver.getPageSource().contains("bburke"));
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig-front?GLO=true");
checkLoggedOut(APP_SERVER_BASE_URL + "/employee-sig-front/");
@@ -291,19 +298,19 @@ public class SamlAdapterTestStrategy extends ExternalResource {
Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
System.out.println("login to form");
loginPage.login("bburke", "password");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee-sig/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee-sig/");
Assert.assertTrue(driver.getPageSource().contains("bburke"));
// visit 2nd app
System.out.println("visit 2nd app ");
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig-front/");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee-sig-front/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee-sig-front/");
Assert.assertTrue(driver.getPageSource().contains("bburke"));
// visit 3rd app
System.out.println("visit 3rd app ");
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig/");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig/");
Assert.assertTrue(driver.getPageSource().contains("bburke"));
// logout of first app
@@ -320,9 +327,9 @@ public class SamlAdapterTestStrategy extends ExternalResource {
public void testPostEncryptedLoginLogout() {
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-enc/");
- Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
loginPage.login("bburke", "password");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-enc/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-enc/");
Assert.assertTrue(driver.getPageSource().contains("bburke"));
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-enc?GLO=true");
checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-enc/");
@@ -330,8 +337,8 @@ public class SamlAdapterTestStrategy extends ExternalResource {
}
public void testPostBadClientSignature() {
driver.navigate().to(APP_SERVER_BASE_URL + "/bad-client-sales-post-sig/");
- Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
- Assert.assertEquals(driver.getTitle(), "We're sorry...");
+ assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertEquals(driver.getTitle(), "We're sorry...");
}
public static interface CheckAuthError {
@@ -340,39 +347,19 @@ public class SamlAdapterTestStrategy extends ExternalResource {
public void testPostBadRealmSignature(CheckAuthError error) {
driver.navigate().to(APP_SERVER_BASE_URL + "/bad-realm-sales-post-sig/");
- Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
loginPage.login("bburke", "password");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/bad-realm-sales-post-sig/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/bad-realm-sales-post-sig/");
System.out.println(driver.getPageSource());
error.check(driver);
}
- private static String createToken(String AUTH_SERVER_URL, AbstractKeycloakRule keycloakRule) {
- KeycloakSession session = keycloakRule.startSession();
- try {
- RealmManager manager = new RealmManager(session);
-
- RealmModel adminRealm = manager.getRealm(Config.getAdminRealm());
- ClientModel adminConsole = adminRealm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
- TokenManager tm = new TokenManager();
- UserModel admin = session.users().getUserByUsername("admin", adminRealm);
- ClientSessionModel clientSession = session.sessions().createClientSession(adminRealm, adminConsole);
- clientSession.setNote(OIDCLoginProtocol.ISSUER, AUTH_SERVER_URL + "/realms/master");
- UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, "admin", null, "form", false, null, null);
- AccessToken token = tm.createClientAccessToken(session, tm.getAccess(null, true, adminConsole, admin), adminRealm, adminConsole, admin, userSession, clientSession);
- return tm.encodeToken(adminRealm, token);
- } finally {
- keycloakRule.stopSession(session, true);
- }
- }
-
-
public void testMetadataPostSignedLoginLogout() throws Exception {
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-metadata/");
- Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
loginPage.login("bburke", "password");
- Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-metadata/");
+ assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-metadata/");
String pageSource = driver.getPageSource();
Assert.assertTrue(pageSource.contains("bburke"));
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-metadata?GLO=true");
@@ -380,30 +367,21 @@ public class SamlAdapterTestStrategy extends ExternalResource {
}
- public static void uploadSP(String AUTH_SERVER_URL, AbstractKeycloakRule keycloakRule) {
- String token = createToken(AUTH_SERVER_URL, keycloakRule);
- final String authHeader = "Bearer " + token;
- ClientRequestFilter authFilter = new ClientRequestFilter() {
- @Override
- public void filter(ClientRequestContext requestContext) throws IOException {
- requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authHeader);
- }
- };
- Client client = ClientBuilder.newBuilder().register(authFilter).build();
- UriBuilder authBase = UriBuilder.fromUri(AUTH_SERVER_URL + "");
- WebTarget adminRealms = client.target(AdminRoot.realmsUrl(authBase));
-
-
- MultipartFormDataOutput formData = new MultipartFormDataOutput();
- InputStream is = SamlAdapterTestStrategy.class.getResourceAsStream("/keycloak-saml/sp-metadata.xml");
- Assert.assertNotNull(is);
- formData.addFormData("file", is, MediaType.APPLICATION_XML_TYPE);
-
- WebTarget upload = adminRealms.path("demo/client-importers/saml2-entity-descriptor/upload");
- System.out.println(upload.getUri());
- Response response = upload.request().post(Entity.entity(formData, MediaType.MULTIPART_FORM_DATA));
- Assert.assertEquals(204, response.getStatus());
- response.close();
- client.close();
+ public static void uploadSP(String AUTH_SERVER_URL) {
+ try {
+ Keycloak keycloak = Keycloak.getInstance(AUTH_SERVER_URL, "master", "admin", "admin", Constants.ADMIN_CONSOLE_CLIENT_ID, null);
+ RealmResource admin = keycloak.realm("demo");
+
+ admin.toRepresentation();
+
+ ClientRepresentation clientRep = admin.convertClientDescription(IOUtils.toString(SamlAdapterTestStrategy.class.getResourceAsStream("/keycloak-saml/sp-metadata.xml")));
+ Response response = admin.clients().create(clientRep);
+
+ assertEquals(201, response.getStatus());
+
+ keycloak.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java
index 2d2ab44..019bfea 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java
@@ -1,11 +1,14 @@
package org.keycloak.testsuite.saml;
+import org.apache.commons.io.IOUtils;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.keycloak.Config;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.Constants;
@@ -22,9 +25,11 @@ import org.keycloak.protocol.saml.mappers.HardcodedRole;
import org.keycloak.protocol.saml.mappers.RoleListMapper;
import org.keycloak.protocol.saml.mappers.RoleNameMapper;
import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.admin.AdminRoot;
import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.rule.AbstractKeycloakRule;
import org.keycloak.testsuite.rule.KeycloakRule;
import org.keycloak.testsuite.rule.WebResource;
import org.keycloak.testsuite.rule.WebRule;
@@ -56,6 +61,8 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
+import static org.junit.Assert.assertEquals;
+
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
@@ -480,30 +487,21 @@ public class SamlBindingTest {
}
public static void uploadSP() {
- String token = createToken();
- final String authHeader = "Bearer " + token;
- ClientRequestFilter authFilter = new ClientRequestFilter() {
- @Override
- public void filter(ClientRequestContext requestContext) throws IOException {
- requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authHeader);
- }
- };
- Client client = ClientBuilder.newBuilder().register(authFilter).build();
- UriBuilder authBase = UriBuilder.fromUri("http://localhost:8081/auth");
- WebTarget adminRealms = client.target(AdminRoot.realmsUrl(authBase));
-
-
- MultipartFormDataOutput formData = new MultipartFormDataOutput();
- InputStream is = SamlBindingTest.class.getResourceAsStream("/saml/sp-metadata.xml");
- Assert.assertNotNull(is);
- formData.addFormData("file", is, MediaType.APPLICATION_XML_TYPE);
-
- WebTarget upload = adminRealms.path("demo/client-importers/saml2-entity-descriptor/upload");
- System.out.println(upload.getUri());
- Response response = upload.request().post(Entity.entity(formData, MediaType.MULTIPART_FORM_DATA));
- Assert.assertEquals(204, response.getStatus());
- response.close();
- client.close();
+ try {
+ Keycloak keycloak = Keycloak.getInstance("http://localhost:8081/auth", "master", "admin", "admin", Constants.ADMIN_CONSOLE_CLIENT_ID, null);
+ RealmResource admin = keycloak.realm("demo");
+
+ admin.toRepresentation();
+
+ ClientRepresentation clientRep = admin.convertClientDescription(IOUtils.toString(SamlBindingTest.class.getResourceAsStream("/saml/sp-metadata.xml")));
+ Response response = admin.clients().create(clientRep);
+
+ assertEquals(201, response.getStatus());
+
+ keycloak.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
diff --git a/testsuite/integration/src/test/resources/client-descriptions/client-oidc.json b/testsuite/integration/src/test/resources/client-descriptions/client-oidc.json
new file mode 100644
index 0000000..51562fd
--- /dev/null
+++ b/testsuite/integration/src/test/resources/client-descriptions/client-oidc.json
@@ -0,0 +1,6 @@
+{
+ "client_name": "Name",
+ "redirect_uris": [
+ "http://localhost"
+ ]
+}
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/client-descriptions/saml-entity-descriptor.xml b/testsuite/integration/src/test/resources/client-descriptions/saml-entity-descriptor.xml
new file mode 100644
index 0000000..b00ab25
--- /dev/null
+++ b/testsuite/integration/src/test/resources/client-descriptions/saml-entity-descriptor.xml
@@ -0,0 +1,82 @@
+<EntityDescriptor
+ xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
+ entityID="loadbalancer-9.siroe.com">
+ <SPSSODescriptor
+ AuthnRequestsSigned="false"
+ WantAssertionsSigned="false"
+ protocolSupportEnumeration=
+ "urn:oasis:names:tc:SAML:2.0:protocol">
+ <KeyDescriptor use="signing">
+ <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <X509Data>
+ <X509Certificate>
+MIICYDCCAgqgAwIBAgICBoowDQYJKoZIhvcNAQEEBQAwgZIxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
+EwpDYWxpZm9ybmlhMRQwEgYDVQQHEwtTYW50YSBDbGFyYTEeMBwGA1UEChMVU3VuIE1pY3Jvc3lz
+dGVtcyBJbmMuMRowGAYDVQQLExFJZGVudGl0eSBTZXJ2aWNlczEcMBoGA1UEAxMTQ2VydGlmaWNh
+dGUgTWFuYWdlcjAeFw0wNjExMDIxOTExMzRaFw0xMDA3MjkxOTExMzRaMDcxEjAQBgNVBAoTCXNp
+cm9lLmNvbTEhMB8GA1UEAxMYbG9hZGJhbGFuY2VyLTkuc2lyb2UuY29tMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQCjOwa5qoaUuVnknqf5pdgAJSEoWlvx/jnUYbkSDpXLzraEiy2UhvwpoBgB
+EeTSUaPPBvboCItchakPI6Z/aFdH3Wmjuij9XD8r1C+q//7sUO0IGn0ORycddHhoo0aSdnnxGf9V
+tREaqKm9dJ7Yn7kQHjo2eryMgYxtr/Z5Il5F+wIDAQABo2AwXjARBglghkgBhvhCAQEEBAMCBkAw
+DgYDVR0PAQH/BAQDAgTwMB8GA1UdIwQYMBaAFDugITflTCfsWyNLTXDl7cMDUKuuMBgGA1UdEQQR
+MA+BDW1hbGxhQHN1bi5jb20wDQYJKoZIhvcNAQEEBQADQQB/6DOB6sRqCZu2OenM9eQR0gube85e
+nTTxU4a7x1naFxzYXK1iQ1vMARKMjDb19QEJIEJKZlDK4uS7yMlf1nFS
+ </X509Certificate>
+ </X509Data>
+ </KeyInfo>
+ </KeyDescriptor>
+ <KeyDescriptor use="encryption">
+ <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <X509Data>
+ <X509Certificate>
+MIICTDCCAfagAwIBAgICBo8wDQYJKoZIhvcNAQEEBQAwgZIxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
+EwpDYWxpZm9ybmlhMRQwEgYDVQQHEwtTYW50YSBDbGFyYTEeMBwGA1UEChMVU3VuIE1pY3Jvc3lz
+dGVtcyBJbmMuMRowGAYDVQQLExFJZGVudGl0eSBTZXJ2aWNlczEcMBoGA1UEAxMTQ2VydGlmaWNh
+dGUgTWFuYWdlcjAeFw0wNjExMDcyMzU2MTdaFw0xMDA4MDMyMzU2MTdaMCMxITAfBgNVBAMTGGxv
+YWRiYWxhbmNlci05LnNpcm9lLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw574iRU6
+HsSO4LXW/OGTXyfsbGv6XRVOoy3v+J1pZ51KKejcDjDJXNkKGn3/356AwIaqbcymWd59T0zSqYfR
+Hn+45uyjYxRBmVJseLpVnOXLub9jsjULfGx0yjH4w+KsZSZCXatoCHbj/RJtkzuZY6V9to/hkH3S
+InQB4a3UAgMCAwEAAaNgMF4wEQYJYIZIAYb4QgEBBAQDAgZAMA4GA1UdDwEB/wQEAwIE8DAfBgNV
+HSMEGDAWgBQ7oCE35Uwn7FsjS01w5e3DA1CrrjAYBgNVHREEETAPgQ1tYWxsYUBzdW4uY29tMA0G
+CSqGSIb3DQEBBAUAA0EAMlbfBg/ff0Xkv4DOR5LEqmfTZKqgdlD81cXynfzlF7XfnOqI6hPIA90I
+x5Ql0ejivIJAYcMGUyA+/YwJg2FGoA==
+ </X509Certificate>
+ </X509Data>
+ </KeyInfo>
+ <EncryptionMethod Algorithm=
+ "https://www.w3.org/2001/04/xmlenc#aes128-cbc">
+ <KeySize xmlns="https://www.w3.org/2001/04/xmlenc#">128</KeySize>
+ </EncryptionMethod>
+ </KeyDescriptor>
+ <SingleLogoutService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
+ Location="https://LoadBalancer-9.siroe.com:3443/federation/SPSloRedirect/metaAlias/sp"
+ ResponseLocation="https://LoadBalancer-9.siroe.com:3443/federation/SPSloRedirect/metaAlias/sp"/>
+ <SingleLogoutService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
+ Location="https://LoadBalancer-9.siroe.com:3443/federation/SPSloSoap/metaAlias/sp"/>
+ <ManageNameIDService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
+ Location="https://LoadBalancer-9.siroe.com:3443/federation/SPMniRedirect/metaAlias/sp"
+ ResponseLocation="https://LoadBalancer-9.siroe.com:3443/federation/SPMniRedirect/metaAlias/sp"/>
+ <ManageNameIDService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
+ Location="https://LoadBalancer-9.siroe.com:3443/federation/SPMniSoap/metaAlias/sp"
+ ResponseLocation="https://LoadBalancer-9.siroe.com:3443/federation/SPMniSoap/metaAlias/sp"/>
+ <NameIDFormat>
+ urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
+ </NameIDFormat>
+ <NameIDFormat>
+ urn:oasis:names:tc:SAML:2.0:nameid-format:transient
+ </NameIDFormat>
+ <AssertionConsumerService
+ isDefault="true"
+ index="0"
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
+ Location="https://LoadBalancer-9.siroe.com:3443/federation/Consumer/metaAlias/sp"/>
+ <AssertionConsumerService
+ index="1"
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
+ Location="https://LoadBalancer-9.siroe.com:3443/federation/Consumer/metaAlias/sp"/>
+ </SPSSODescriptor>
+</EntityDescriptor>
diff --git a/testsuite/tomcat6/src/test/java/org/keycloak/testsuite/TomcatSamlTest.java b/testsuite/tomcat6/src/test/java/org/keycloak/testsuite/TomcatSamlTest.java
index 98eec5a..b16f954 100755
--- a/testsuite/tomcat6/src/test/java/org/keycloak/testsuite/TomcatSamlTest.java
+++ b/testsuite/tomcat6/src/test/java/org/keycloak/testsuite/TomcatSamlTest.java
@@ -30,7 +30,6 @@ import org.junit.Test;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.services.managers.RealmManager;
-import org.keycloak.testsuite.adapter.AdapterTestStrategy;
import org.keycloak.testsuite.keycloaksaml.SamlAdapterTestStrategy;
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
import org.openqa.selenium.WebDriver;
@@ -73,7 +72,7 @@ public class TomcatSamlTest {
tomcat.deploySaml("/bad-client-sales-post-sig", "bad-client-signed-post");
tomcat.deploySaml("/bad-realm-sales-post-sig", "bad-realm-signed-post");
tomcat.deploySaml("/sales-post-enc", "encrypted-post");
- SamlAdapterTestStrategy.uploadSP("http://localhost:8081/auth", keycloakRule);
+ SamlAdapterTestStrategy.uploadSP("http://localhost:8081/auth");
tomcat.start();