keycloak-aplcache
Changes
saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SALM2PostBindingLoginResponseBuilder.java 147(+15 -132)
saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2PostBindingBuilder.java 133(+133 -0)
saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2PostBindingErrorResponseBuilder.java 57(+57 -0)
saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2PostBindingLogoutResponseBuilder.java 69(+69 -0)
Details
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2PostBindingBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2PostBindingBuilder.java
new file mode 100755
index 0000000..a1b105c
--- /dev/null
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2PostBindingBuilder.java
@@ -0,0 +1,133 @@
+package org.keycloak.protocol.saml;
+
+import org.picketlink.common.constants.GeneralConstants;
+import org.picketlink.common.exceptions.ConfigurationException;
+import org.picketlink.common.exceptions.ProcessingException;
+import org.picketlink.common.util.DocumentUtil;
+import org.picketlink.identity.federation.web.util.PostBindingUtil;
+import org.w3c.dom.Document;
+
+import javax.ws.rs.core.CacheControl;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+
+import static org.picketlink.common.util.StringUtil.isNotNull;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SAML2PostBindingBuilder<T extends SAML2PostBindingBuilder> {
+ protected KeyPair signingKeyPair;
+ protected X509Certificate signingCertificate;
+ protected boolean signed;
+ protected String signatureDigestMethod;
+ protected String signatureMethod;
+ protected String relayState;
+ protected String destination;
+ protected String responseIssuer;
+
+ public T sign(KeyPair keyPair) {
+ this.signingKeyPair = keyPair;
+ this.signed = true;
+ return (T)this;
+ }
+
+ public T sign(PrivateKey privateKey, PublicKey publicKey) {
+ this.signingKeyPair = new KeyPair(publicKey, privateKey);
+ this.signed = true;
+ return (T)this;
+ }
+
+ public T sign(KeyPair keyPair, X509Certificate cert) {
+ this.signingKeyPair = keyPair;
+ this.signingCertificate = cert;
+ this.signed = true;
+ return (T)this;
+ }
+
+ public T signatureDigestMethod(String method) {
+ this.signatureDigestMethod = method;
+ return (T)this;
+ }
+
+ public T signatureMethod(String method) {
+ this.signatureMethod = method;
+ return (T)this;
+ }
+
+ public T sign(PrivateKey privateKey, PublicKey publicKey, X509Certificate cert) {
+ this.signingKeyPair = new KeyPair(publicKey, privateKey);
+ this.signingCertificate = cert;
+ this.signed = true;
+ return (T)this;
+ }
+
+ public T destination(String destination) {
+ this.destination = destination;
+ return (T)this;
+ }
+
+ public T responseIssuer(String issuer) {
+ this.responseIssuer = issuer;
+ return (T)this;
+ }
+
+ public T relayState(String relayState) {
+ this.relayState = relayState;
+ return (T)this;
+ }
+
+
+
+ protected void signDocument(Document samlDocument) throws ProcessingException {
+ SamlProtocolUtils.signDocument(samlDocument, signingKeyPair, signatureMethod, signatureDigestMethod, signingCertificate);
+ }
+
+ protected Response buildResponse(Document responseDoc) throws ProcessingException, ConfigurationException, IOException {
+ byte[] responseBytes = DocumentUtil.getDocumentAsString(responseDoc).getBytes("UTF-8");
+ String samlResponse = PostBindingUtil.base64Encode(new String(responseBytes));
+
+ if (destination == null) {
+ throw SALM2PostBindingLoginResponseBuilder.logger.nullValueError("Destination is null");
+ }
+
+ StringBuilder builder = new StringBuilder();
+
+ String key = GeneralConstants.SAML_RESPONSE_KEY;
+ builder.append("<HTML>");
+ builder.append("<HEAD>");
+
+ builder.append("<TITLE>HTTP Post Binding Response (Response)</TITLE>");
+ builder.append("</HEAD>");
+ builder.append("<BODY Onload=\"document.forms[0].submit()\">");
+
+ builder.append("<FORM METHOD=\"POST\" ACTION=\"" + destination + "\">");
+ builder.append("<INPUT TYPE=\"HIDDEN\" NAME=\"" + key + "\"" + " VALUE=\"" + samlResponse + "\"/>");
+
+ if (isNotNull(relayState)) {
+ builder.append("<INPUT TYPE=\"HIDDEN\" NAME=\"RelayState\" " + "VALUE=\"" + relayState + "\"/>");
+ }
+
+ builder.append("<NOSCRIPT>");
+ builder.append("<P>JavaScript is disabled. We strongly recommend to enable it. Click the button below to continue.</P>");
+ builder.append("<INPUT TYPE=\"SUBMIT\" VALUE=\"CONTINUE\" />");
+ builder.append("</NOSCRIPT>");
+
+ builder.append("</FORM></BODY></HTML>");
+
+ String str = builder.toString();
+
+ CacheControl cacheControl = new CacheControl();
+ cacheControl.setNoCache(true);
+ return Response.ok(str, MediaType.TEXT_HTML_TYPE)
+ .header("Pragma", "no-cache")
+ .header("Cache-Control", "no-cache, no-store").build();
+ }
+
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2PostBindingErrorResponseBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2PostBindingErrorResponseBuilder.java
new file mode 100755
index 0000000..6d56e51
--- /dev/null
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2PostBindingErrorResponseBuilder.java
@@ -0,0 +1,57 @@
+package org.keycloak.protocol.saml;
+
+import org.picketlink.common.constants.JBossSAMLURIConstants;
+import org.picketlink.common.exceptions.ConfigurationException;
+import org.picketlink.common.exceptions.ProcessingException;
+import org.picketlink.identity.federation.api.saml.v2.response.SAML2Response;
+import org.picketlink.identity.federation.core.saml.v2.common.IDGenerator;
+import org.picketlink.identity.federation.core.saml.v2.factories.JBossSAMLAuthnResponseFactory;
+import org.picketlink.identity.federation.core.saml.v2.holders.IDPInfoHolder;
+import org.picketlink.identity.federation.core.saml.v2.holders.IssuerInfoHolder;
+import org.picketlink.identity.federation.core.saml.v2.holders.SPInfoHolder;
+import org.picketlink.identity.federation.saml.v2.protocol.ResponseType;
+import org.w3c.dom.Document;
+
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.StringWriter;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SAML2PostBindingErrorResponseBuilder extends SAML2PostBindingBuilder<SAML2PostBindingErrorResponseBuilder> {
+
+ public Document getErrorResponse(String status) throws ProcessingException {
+ Document samlResponse = null;
+ ResponseType responseType = null;
+
+ SAML2Response saml2Response = new SAML2Response();
+
+ // Create a response type
+ String id = IDGenerator.create("ID_");
+
+ IssuerInfoHolder issuerHolder = new IssuerInfoHolder(responseIssuer);
+ issuerHolder.setStatusCode(status);
+
+ IDPInfoHolder idp = new IDPInfoHolder();
+ idp.setNameIDFormatValue(null);
+ idp.setNameIDFormat(JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get());
+
+ SPInfoHolder sp = new SPInfoHolder();
+ sp.setResponseDestinationURI(destination);
+
+ responseType = saml2Response.createResponseType(id);
+ responseType.setStatus(JBossSAMLAuthnResponseFactory.createStatusTypeForResponder(status));
+ responseType.setDestination(destination);
+
+ if (signed) {
+ signDocument(samlResponse);
+ }
+ return samlResponse;
+ }
+
+ public Response buildErrorResponse(String status) throws ConfigurationException, ProcessingException, IOException {
+ Document doc = getErrorResponse(status);
+ return buildResponse(doc);
+ }}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2PostBindingLogoutResponseBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2PostBindingLogoutResponseBuilder.java
new file mode 100755
index 0000000..70c1909
--- /dev/null
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2PostBindingLogoutResponseBuilder.java
@@ -0,0 +1,69 @@
+package org.keycloak.protocol.saml;
+
+import org.picketlink.common.constants.JBossSAMLURIConstants;
+import org.picketlink.common.exceptions.ConfigurationException;
+import org.picketlink.common.exceptions.ParsingException;
+import org.picketlink.common.exceptions.ProcessingException;
+import org.picketlink.identity.federation.api.saml.v2.request.SAML2Request;
+import org.picketlink.identity.federation.api.saml.v2.response.SAML2Response;
+import org.picketlink.identity.federation.core.saml.v2.common.IDGenerator;
+import org.picketlink.identity.federation.core.saml.v2.factories.JBossSAMLAuthnResponseFactory;
+import org.picketlink.identity.federation.core.saml.v2.holders.IDPInfoHolder;
+import org.picketlink.identity.federation.core.saml.v2.holders.IssuerInfoHolder;
+import org.picketlink.identity.federation.core.saml.v2.holders.SPInfoHolder;
+import org.picketlink.identity.federation.core.saml.v2.util.DocumentUtil;
+import org.picketlink.identity.federation.core.saml.v2.util.XMLTimeUtil;
+import org.picketlink.identity.federation.core.sts.PicketLinkCoreSTS;
+import org.picketlink.identity.federation.saml.v2.assertion.NameIDType;
+import org.picketlink.identity.federation.saml.v2.protocol.LogoutRequestType;
+import org.picketlink.identity.federation.saml.v2.protocol.ResponseType;
+import org.picketlink.identity.federation.web.util.PostBindingUtil;
+import org.w3c.dom.Document;
+
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.net.URI;
+import java.security.KeyPair;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SAML2PostBindingLogoutResponseBuilder extends SAML2PostBindingBuilder<SAML2PostBindingLogoutResponseBuilder> {
+ protected String userPrincipal;
+
+ public SAML2PostBindingLogoutResponseBuilder userPrincipal(String userPrincipal) {
+ this.userPrincipal = userPrincipal;
+ return this;
+ }
+
+ public String buildRequestString() {
+ try {
+ Document logoutRequestDocument = new SAML2Request().convert(createLogoutRequest());
+ if (signed) {
+ signDocument(logoutRequestDocument);
+ }
+ byte[] responseBytes = DocumentUtil.getDocumentAsString(logoutRequestDocument).getBytes("UTF-8");
+ return PostBindingUtil.base64Encode(new String(responseBytes));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private LogoutRequestType createLogoutRequest() throws ConfigurationException {
+ LogoutRequestType lort = new SAML2Request().createLogoutRequest(responseIssuer);
+
+ NameIDType nameID = new NameIDType();
+ nameID.setValue(userPrincipal);
+ //Deal with NameID Format
+ String nameIDFormat = JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get();
+ nameID.setFormat(URI.create(nameIDFormat));
+ lort.setNameID(nameID);
+
+ long assertionValidity = PicketLinkCoreSTS.instance().getConfiguration().getIssuedTokenTimeout();
+
+ lort.setNotOnOrAfter(XMLTimeUtil.add(lort.getIssueInstant(), assertionValidity));
+ lort.setDestination(URI.create(destination));
+ return lort;
+ }
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java
new file mode 100755
index 0000000..342f089
--- /dev/null
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java
@@ -0,0 +1,66 @@
+package org.keycloak.protocol.saml;
+
+import org.keycloak.VerificationException;
+import org.keycloak.models.ClientModel;
+import org.keycloak.util.PemUtils;
+import org.picketlink.common.exceptions.ProcessingException;
+import org.picketlink.identity.federation.api.saml.v2.sig.SAML2Signature;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import java.security.KeyPair;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SamlProtocolUtils {
+
+ public static void verifyPostBindingSignature(ClientModel client, Document document) throws VerificationException {
+ if (!"true".equals(client.getAttribute("samlClientSignature"))) {
+ return;
+ }
+ SAML2Signature saml2Signature = new SAML2Signature();
+ String publicKeyPem = client.getAttribute(ClientModel.PUBLIC_KEY);
+ if (publicKeyPem == null) throw new VerificationException("Client does not have a public key.");
+ PublicKey publicKey = null;
+ try {
+ publicKey = PemUtils.decodePublicKey(publicKeyPem);
+ } catch (Exception e) {
+ throw new VerificationException("Could not decode public key", e);
+ }
+ try {
+ if (!saml2Signature.validate(document, publicKey)) {
+ throw new VerificationException("Invalid signature on document");
+ }
+ } catch (ProcessingException e) {
+ throw new VerificationException("Error validating signature", e);
+ }
+ }
+
+ public static void signDocument(Document samlDocument, KeyPair signingKeyPair, String signatureMethod, String signatureDigestMethod, X509Certificate signingCertificate) throws ProcessingException {
+ SAML2Signature samlSignature = new SAML2Signature();
+
+ if (signatureMethod != null) {
+ samlSignature.setSignatureMethod(signatureMethod);
+ }
+
+ if (signatureDigestMethod != null) {
+ samlSignature.setDigestMethod(signatureDigestMethod);
+ }
+
+ Node nextSibling = samlSignature.getNextSiblingOfIssuer(samlDocument);
+
+ samlSignature.setNextSibling(nextSibling);
+
+ if (signingCertificate != null) {
+ samlSignature.setX509Certificate(signingCertificate);
+ }
+
+ samlSignature.signSAMLDocument(samlDocument, signingKeyPair);
+ }
+
+
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAMLRequestParser.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAMLRequestParser.java
index 4d5b6d4..db19892 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAMLRequestParser.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAMLRequestParser.java
@@ -43,6 +43,5 @@ public class SAMLRequestParser {
logger.samlBase64DecodingError(e);
}
return null;
-
}
}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
index 855b476..708010e 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
@@ -1,13 +1,11 @@
package org.keycloak.protocol.saml;
import org.jboss.logging.Logger;
-import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.HttpResponse;
import org.keycloak.ClientConnection;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.events.Details;
+import org.keycloak.VerificationException;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
@@ -27,15 +25,14 @@ import org.picketlink.identity.federation.core.saml.v2.common.SAMLDocumentHolder
import org.picketlink.identity.federation.saml.v2.SAML2Object;
import org.picketlink.identity.federation.saml.v2.protocol.AuthnRequestType;
import org.picketlink.identity.federation.saml.v2.protocol.LogoutRequestType;
+import org.picketlink.identity.federation.saml.v2.protocol.RequestAbstractType;
+import org.w3c.dom.Document;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
-import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
-import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
-import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
@@ -45,8 +42,6 @@ import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Providers;
import java.net.URI;
-import java.util.HashMap;
-import java.util.Map;
/**
* Resource class for the oauth/openid connect token service
@@ -137,24 +132,7 @@ public class SamlService {
SAML2Object samlObject = documentHolder.getSamlObject();
- if (samlObject instanceof AuthnRequestType) {
- event.event(EventType.LOGIN);
- // Get the SAML Request Message
- AuthnRequestType requestAbstractType = (AuthnRequestType) samlObject;
- return loginRequest(relayState, requestAbstractType);
- } else if (samlObject instanceof LogoutRequestType) {
- event.event(EventType.LOGOUT);
- LogoutRequestType requestAbstractType = (LogoutRequestType) samlObject;
- return logoutRequest(relayState, requestAbstractType);
-
- } else {
- event.event(EventType.LOGIN_ERROR);
- event.error(Errors.INVALID_TOKEN);
- return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Invalid Request");
- }
- }
-
- protected Response loginRequest(String relayState, AuthnRequestType requestAbstractType) {
+ RequestAbstractType requestAbstractType = (RequestAbstractType)samlObject;
String issuer = requestAbstractType.getIssuer().getValue();
ClientModel client = realm.findClient(issuer);
@@ -176,6 +154,32 @@ public class SamlService {
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "direct-grants-only clients are not allowed to initiate browser login");
}
+ try {
+ SamlProtocolUtils.verifyPostBindingSignature(client, documentHolder.getSamlDocument());
+ } catch (VerificationException e) {
+ logger.error("request validation failed", e);
+ event.error(Errors.INVALID_CLIENT);
+ return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Invalid requester.");
+ }
+ if (samlObject instanceof AuthnRequestType) {
+ event.event(EventType.LOGIN);
+ // Get the SAML Request Message
+ AuthnRequestType authn = (AuthnRequestType) samlObject;
+ return loginRequest(relayState, authn, client);
+ } else if (samlObject instanceof LogoutRequestType) {
+ event.event(EventType.LOGOUT);
+ LogoutRequestType logout = (LogoutRequestType) samlObject;
+ return logoutRequest(logout, client);
+
+ } else {
+ event.event(EventType.LOGIN_ERROR);
+ event.error(Errors.INVALID_TOKEN);
+ return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Invalid Request");
+ }
+ }
+
+ protected Response loginRequest(String relayState, AuthnRequestType requestAbstractType, ClientModel client) {
+
URI redirectUri = requestAbstractType.getAssertionConsumerServiceURL();
String redirect = OpenIDConnectService.verifyRedirectUri(uriInfo, redirectUri.toString(), realm, client);
@@ -186,10 +190,10 @@ public class SamlService {
ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
- clientSession.setAuthMethod(SamlLogin.LOGIN_PROTOCOL);
+ clientSession.setAuthMethod(SalmProtocol.LOGIN_PROTOCOL);
clientSession.setRedirectUri(redirect);
clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE);
- clientSession.setNote(SamlLogin.SAML_BINDING, SamlLogin.SAML_POST_BINDING);
+ clientSession.setNote(SalmProtocol.SAML_BINDING, SalmProtocol.SAML_POST_BINDING);
clientSession.setNote(GeneralConstants.RELAY_STATE, relayState);
clientSession.setNote("REQUEST_ID", requestAbstractType.getID());
@@ -212,28 +216,7 @@ public class SamlService {
return forms.createLogin();
}
- protected Response logoutRequest(String relayState, LogoutRequestType requestAbstractType) {
- String issuer = requestAbstractType.getIssuer().getValue();
- ClientModel client = realm.findClient(issuer);
-
- if (client == null) {
- event.error(Errors.CLIENT_NOT_FOUND);
- return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Unknown login requester.");
- }
-
- if (!client.isEnabled()) {
- event.error(Errors.CLIENT_DISABLED);
- return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Login requester not enabled.");
- }
- if ((client instanceof ApplicationModel) && ((ApplicationModel)client).isBearerOnly()) {
- event.error(Errors.NOT_ALLOWED);
- return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Bearer-only applications are not allowed to initiate browser login");
- }
- if (client.isDirectGrantsOnly()) {
- event.error(Errors.NOT_ALLOWED);
- return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "direct-grants-only clients are not allowed to initiate browser login");
- }
-
+ protected Response logoutRequest(LogoutRequestType requestAbstractType, ClientModel client) {
// authenticate identity cookie, but ignore an access token timeout as we're logging out anyways.
AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, uriInfo, clientConnection, headers, false);
if (authResult != null) {
diff --git a/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.protocol.LoginProtocolFactory b/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.protocol.LoginProtocolFactory
index 632a1db..d0a2dd0 100755
--- a/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.protocol.LoginProtocolFactory
+++ b/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.protocol.LoginProtocolFactory
@@ -1 +1 @@
-org.keycloak.protocol.saml.SamlLoginFactory
\ No newline at end of file
+org.keycloak.protocol.saml.SamlProtocolFactory
\ No newline at end of file
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
index 4cfaaa3..620f5e2 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
@@ -157,11 +157,11 @@ public class AccountTest {
});
}
-// @Test
-// @Ignore
-// public void runit() throws Exception {
-// Thread.sleep(10000000);
-// }
+ @Test
+ @Ignore
+ public void runit() throws Exception {
+ Thread.sleep(10000000);
+ }
@Test
public void returnToAppFromQueryParam() {
diff --git a/testsuite/integration/src/test/resources/testsaml.json b/testsuite/integration/src/test/resources/testsaml.json
index 198f170..0cd30ba 100755
--- a/testsuite/integration/src/test/resources/testsaml.json
+++ b/testsuite/integration/src/test/resources/testsaml.json
@@ -32,12 +32,31 @@
"name": "http://localhost:8080/sales-post/",
"enabled": true,
"fullScopeAllowed": true,
+ "protocol": "saml",
"baseUrl": "http://localhost:8080/sales-post",
"adminUrl": "http://localhost:8080/sales-post",
"redirectUris": [
"http://localhost:8080/sales-post/*"
]
- }
+ },
+ {
+ "name": "http://localhost:8080/sales-post-sig/",
+ "enabled": true,
+ "protocol": "saml",
+ "fullScopeAllowed": true,
+ "baseUrl": "http://localhost:8080/sales-post-sig",
+ "adminUrl": "http://localhost:8080/sales-post-sig",
+ "redirectUris": [
+ "http://localhost:8080/sales-post-sig/*"
+ ],
+ "attributes": {
+ "samlServerSignature": "true",
+ "samlClientSignature": "true",
+ "privateKey": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
+ "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQAB",
+ "X509Certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
+ }
+ }
],
"roles" : {
"realm" : [