keycloak-aplcache
Changes
pom.xml 2(+1 -1)
Details
diff --git a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
index faee3c8..82c2ebc 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
@@ -22,6 +22,7 @@ public class ApplicationRepresentation {
protected Integer notBefore;
protected Boolean bearerOnly;
protected Boolean publicClient;
+ protected Boolean frontchannelLogout;
protected String protocol;
protected Map<String, String> attributes;
protected Boolean fullScopeAllowed;
@@ -179,4 +180,12 @@ public class ApplicationRepresentation {
public void setRegisteredNodes(Map<String, Integer> registeredNodes) {
this.registeredNodes = registeredNodes;
}
+
+ public Boolean isFrontchannelLogout() {
+ return frontchannelLogout;
+ }
+
+ public void setFrontchannelLogout(Boolean frontchannelLogout) {
+ this.frontchannelLogout = frontchannelLogout;
+ }
}
diff --git a/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java
index e61cdfc..de65ae6 100755
--- a/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java
@@ -21,6 +21,7 @@ public class OAuthClientRepresentation {
protected Map<String, String> attributes;
protected Boolean directGrantsOnly;
protected Boolean fullScopeAllowed;
+ protected Boolean frontchannelLogout;
public String getId() {
@@ -126,4 +127,12 @@ public class OAuthClientRepresentation {
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
+
+ public Boolean isFrontchannelLogout() {
+ return frontchannelLogout;
+ }
+
+ public void setFrontchannelLogout(Boolean frontchannelLogout) {
+ this.frontchannelLogout = frontchannelLogout;
+ }
}
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 a96e217..42c4423 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
@@ -230,6 +230,7 @@ public class ModelToRepresentation {
rep.setEnabled(applicationModel.isEnabled());
rep.setAdminUrl(applicationModel.getManagementUrl());
rep.setPublicClient(applicationModel.isPublicClient());
+ rep.setFrontchannelLogout(applicationModel.isFrontchannelLogout());
rep.setProtocol(applicationModel.getProtocol());
rep.setAttributes(applicationModel.getAttributes());
rep.setFullScopeAllowed(applicationModel.isFullScopeAllowed());
@@ -266,6 +267,7 @@ public class ModelToRepresentation {
rep.setName(model.getClientId());
rep.setEnabled(model.isEnabled());
rep.setPublicClient(model.isPublicClient());
+ rep.setFrontchannelLogout(model.isFrontchannelLogout());
rep.setProtocol(model.getProtocol());
rep.setAttributes(model.getAttributes());
rep.setFullScopeAllowed(model.isFullScopeAllowed());
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 50907bc..aede6a2 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
@@ -389,6 +389,7 @@ public class RepresentationToModel {
applicationModel.setBaseUrl(resourceRep.getBaseUrl());
if (resourceRep.isBearerOnly() != null) applicationModel.setBearerOnly(resourceRep.isBearerOnly());
if (resourceRep.isPublicClient() != null) applicationModel.setPublicClient(resourceRep.isPublicClient());
+ if (resourceRep.isFrontchannelLogout() != null) applicationModel.setFrontchannelLogout(resourceRep.isFrontchannelLogout());
if (resourceRep.getProtocol() != null) applicationModel.setProtocol(resourceRep.getProtocol());
if (resourceRep.isFullScopeAllowed() != null) {
applicationModel.setFullScopeAllowed(resourceRep.isFullScopeAllowed());
@@ -475,6 +476,7 @@ public class RepresentationToModel {
if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly());
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.getAdminUrl() != null) resource.setManagementUrl(rep.getAdminUrl());
if (rep.getBaseUrl() != null) resource.setBaseUrl(rep.getBaseUrl());
if (rep.isSurrogateAuthRequired() != null) resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired());
@@ -596,6 +598,7 @@ public class RepresentationToModel {
if (rep.getName() != null) model.setClientId(rep.getName());
if (rep.isEnabled() != null) model.setEnabled(rep.isEnabled());
if (rep.isPublicClient() != null) model.setPublicClient(rep.isPublicClient());
+ if (rep.isFrontchannelLogout() != null) model.setFrontchannelLogout(rep.isFrontchannelLogout());
if (rep.isFullScopeAllowed() != null) model.setFullScopeAllowed(rep.isFullScopeAllowed());
if (rep.isDirectGrantsOnly() != null) model.setDirectGrantsOnly(rep.isDirectGrantsOnly());
if (rep.getClaims() != null) {
pom.xml 2(+1 -1)
diff --git a/pom.xml b/pom.xml
index 8e645aa..7ae9a07 100755
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@
<resteasy.version.latest>3.0.9.Final</resteasy.version.latest>
<!-- <undertow.version>1.1.0.Final</undertow.version> -->
<undertow.version>1.1.1.Final</undertow.version>
- <picketlink.version>2.7.0.CR2</picketlink.version>
+ <picketlink.version>2.7.0.CR3</picketlink.version>
<picketbox.ldap.version>1.0.2.Final</picketbox.ldap.version>
<mongo.driver.version>2.11.3</mongo.driver.version>
<jboss.logging.version>3.1.4.GA</jboss.logging.version>
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java
index 84cf7ee..d17c724 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java
@@ -1,5 +1,6 @@
package org.keycloak.protocol.saml;
+import org.jboss.logging.Logger;
import org.picketlink.common.constants.GeneralConstants;
import org.picketlink.common.constants.JBossSAMLConstants;
import org.picketlink.common.constants.JBossSAMLURIConstants;
@@ -38,6 +39,7 @@ import static org.picketlink.common.util.StringUtil.isNotNull;
* @version $Revision: 1 $
*/
public class SAML2BindingBuilder<T extends SAML2BindingBuilder> {
+ protected static final Logger logger = Logger.getLogger(SAML2BindingBuilder.class);
protected KeyPair signingKeyPair;
protected X509Certificate signingCertificate;
@@ -148,6 +150,9 @@ public class SAML2BindingBuilder<T extends SAML2BindingBuilder> {
public Response request() throws ConfigurationException, ProcessingException, IOException {
return buildResponse(document, destination, true);
}
+ public Response request(String actionUrl) throws ConfigurationException, ProcessingException, IOException {
+ return buildResponse(document, actionUrl, true);
+ }
public Response response() throws ConfigurationException, ProcessingException, IOException {
return buildResponse(document, destination, false);
}
@@ -186,13 +191,16 @@ public class SAML2BindingBuilder<T extends SAML2BindingBuilder> {
return response(destination, false);
}
+ public Response request(String redirect) throws ProcessingException, ConfigurationException, IOException {
+ return response(redirect, true);
+ }
public Response request() throws ProcessingException, ConfigurationException, IOException {
return response(destination, true);
}
private Response response(String redirectUri, boolean asRequest) throws ProcessingException, ConfigurationException, IOException {
URI uri = responseUri(redirectUri, asRequest);
-
+ if (logger.isDebugEnabled()) logger.trace("redirect-binding uri: " + uri.toString());
CacheControl cacheControl = new CacheControl();
cacheControl.setNoCache(true);
return Response.status(302).location(uri)
@@ -339,7 +347,9 @@ public class SAML2BindingBuilder<T extends SAML2BindingBuilder> {
}
protected String base64Encoded(Document document) throws ConfigurationException, ProcessingException, IOException {
- byte[] responseBytes = org.picketlink.identity.federation.core.saml.v2.util.DocumentUtil.getDocumentAsString(document).getBytes("UTF-8");
+ String documentAsString = org.picketlink.identity.federation.core.saml.v2.util.DocumentUtil.getDocumentAsString(document);
+ logger.debugv("saml docment: {0}", documentAsString);
+ byte[] responseBytes = documentAsString.getBytes("UTF-8");
return RedirectBindingUtil.deflateBase64URLEncode(responseBytes);
}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutRequestBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutRequestBuilder.java
index 65c902c..1d76e2f 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutRequestBuilder.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutRequestBuilder.java
@@ -53,6 +53,13 @@ public class SAML2LogoutRequestBuilder extends SAML2BindingBuilder<SAML2LogoutRe
nameID.setFormat(URI.create(nameIDFormat));
lort.setNameID(nameID);
+ if (issuer != null) {
+ NameIDType issuerID = new NameIDType();
+ issuerID.setValue(issuer);
+ lort.setIssuer(issuerID);
+ }
+
+
long assertionValidity = PicketLinkCoreSTS.instance().getConfiguration().getIssuedTokenTimeout();
lort.setNotOnOrAfter(XMLTimeUtil.add(lort.getIssueInstant(), assertionValidity));
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 f3bc382..ede181d 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
@@ -307,9 +307,10 @@ public class SamlProtocol implements LoginProtocol {
SAML2LogoutRequestBuilder logoutBuilder = createLogoutRequest(clientSession, client);
try {
if (isLogoutPostBindingForClient(app)) {
- return logoutBuilder.postBinding().response(bindingUri);
+ return logoutBuilder.postBinding().request(bindingUri);
} else {
- return logoutBuilder.redirectBinding().response(bindingUri);
+ logger.debug("frontchannel redirect binding");
+ return logoutBuilder.redirectBinding().request(bindingUri);
}
} catch (ConfigurationException e) {
throw new RuntimeException(e);
@@ -325,6 +326,7 @@ public class SamlProtocol implements LoginProtocol {
@Override
public Response finishLogout(UserSessionModel userSession) {
+ logger.debug("finishLogout");
SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
builder.logoutRequestID(userSession.getNote(SAML_LOGOUT_REQUEST_ID));
builder.destination(userSession.getNote(SAML_LOGOUT_ISSUER));
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 e4bacf9..4320f4e 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
@@ -136,6 +136,7 @@ public class SamlService {
event.error(Errors.INVALID_TOKEN);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Invalid Request");
}
+ logger.debug("logout response");
return authManager.browserLogout(session, realm, userSession, uriInfo, clientConnection);
}
@@ -183,12 +184,15 @@ public class SamlService {
event.error(Errors.INVALID_SIGNATURE);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Invalid requester.");
}
+ logger.debug("verified request");
if (samlObject instanceof AuthnRequestType) {
+ logger.debug("** login request");
event.event(EventType.LOGIN);
// Get the SAML Request Message
AuthnRequestType authn = (AuthnRequestType) samlObject;
return loginRequest(relayState, authn, client);
} else if (samlObject instanceof LogoutRequestType) {
+ logger.debug("** logout request");
event.event(EventType.LOGOUT);
LogoutRequestType logout = (LogoutRequestType) samlObject;
return logoutRequest(logout, client, relayState);
@@ -306,6 +310,13 @@ public class SamlService {
userSession.setNote(SamlProtocol.SAML_LOGOUT_BINDING, logoutBinding);
userSession.setNote(SamlProtocol.SAML_LOGOUT_ISSUER, logoutRequest.getIssuer().getValue());
userSession.setNote(AuthenticationManager.KEYCLOAK_LOGOUT_PROTOCOL, SamlProtocol.LOGIN_PROTOCOL);
+ // remove client from logout requests
+ for (ClientSessionModel clientSession : userSession.getClientSessions()) {
+ if (clientSession.getClient().getId().equals(client.getId())) {
+ clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT);
+ }
+ }
+ logger.debug("browser Logout");
return authManager.browserLogout(session, realm, userSession, uriInfo, clientConnection);
}
@@ -450,6 +461,7 @@ public class SamlService {
public Response redirectBinding(@QueryParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
@QueryParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
@QueryParam(GeneralConstants.RELAY_STATE) String relayState) {
+ logger.debug("SAML GET");
return new RedirectBindingProtocol().execute(samlRequest, samlResponse, relayState);
}
@@ -461,6 +473,7 @@ public class SamlService {
public Response postBinding(@FormParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
@FormParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
@FormParam(GeneralConstants.RELAY_STATE) String relayState) {
+ logger.debug("SAML POST");
return new PostBindingProtocol().execute(samlRequest, samlResponse, relayState);
}
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index 51df254..d02ad2b 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -115,19 +115,21 @@ public class AuthenticationManager {
List<ClientSessionModel> redirectClients = new LinkedList<ClientSessionModel>();
for (ClientSessionModel clientSession : userSession.getClientSessions()) {
ClientModel client = clientSession.getClient();
+ if (clientSession.getAction() == ClientSessionModel.Action.LOGGED_OUT) continue;
if (client.isFrontchannelLogout()) {
String authMethod = clientSession.getAuthMethod();
if (authMethod == null) continue; // must be a keycloak service like account
redirectClients.add(clientSession);
continue;
}
- if (client instanceof ApplicationModel && !client.isFrontchannelLogout() && clientSession.getAction() != ClientSessionModel.Action.LOGGED_OUT) {
+ if (client instanceof ApplicationModel && !client.isFrontchannelLogout()) {
String authMethod = clientSession.getAuthMethod();
if (authMethod == null) continue; // must be a keycloak service like account
LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod);
protocol.setRealm(realm)
.setUriInfo(uriInfo);
try {
+ logger.debugv("backchannel logout to: {0}", client.getClientId());
protocol.backchannelLogout(userSession, clientSession);
clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT);
} catch (Exception e) {
@@ -147,8 +149,12 @@ public class AuthenticationManager {
// setting this to logged out cuz I"m not sure protocols can always verify that the client was logged out or not
nextRedirectClient.setAction(ClientSessionModel.Action.LOGGED_OUT);
try {
+ logger.debugv("frontchannel logout to: {0}", nextRedirectClient.getClient().getClientId());
Response response = protocol.frontchannelLogout(userSession, nextRedirectClient);
- if (response != null) return response;
+ if (response != null) {
+ logger.debug("returning frontchannel logout request to client");
+ return response;
+ }
} catch (Exception e) {
logger.warn("Failed to logout client, continuing", e);
}
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 55f4726..25a3414 100755
--- a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
@@ -328,7 +328,7 @@ public class ResourceAdminManager {
return new GlobalRequestResult();
}
- if (logger.isDebugEnabled()) logger.info("Sending push revocation to URLS: " + mgmtUrls);
+ if (logger.isDebugEnabled()) logger.debug("Sending push revocation to URLS: " + mgmtUrls);
// Propagate this to all hosts
GlobalRequestResult result = new GlobalRequestResult();
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 d633120..b600305 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
@@ -54,6 +54,7 @@ public class SamlBindingTest {
initializeSamlSecuredWar("/saml/signed-post-persistent", "/sales-post-sig-persistent", "post-sig-persistent.war", classLoader);
initializeSamlSecuredWar("/saml/signed-metadata", "/sales-metadata", "post-metadata.war", classLoader);
initializeSamlSecuredWar("/saml/signed-get", "/employee-sig", "employee-sig.war", classLoader);
+ initializeSamlSecuredWar("/saml/signed-front-get", "/employee-sig-front", "employee-sig-front.war", classLoader);
initializeSamlSecuredWar("/saml/bad-client-signed-post", "/bad-client-sales-post-sig", "bad-client-post-sig.war", classLoader);
initializeSamlSecuredWar("/saml/bad-realm-signed-post", "/bad-realm-sales-post-sig", "bad-realm-post-sig.war", classLoader);
initializeSamlSecuredWar("/saml/encrypted-post", "/sales-post-enc", "post-enc.war", classLoader);
@@ -79,9 +80,14 @@ public class SamlBindingTest {
Thread.sleep(10000000);
}
- protected void checkLoggedOut() {
- Assert.assertTrue(driver.getPageSource().contains("request-path: /logout.jsp"));
- Assert.assertTrue(driver.getPageSource().contains("principal=null"));
+ protected void checkLoggedOut(String mainUrl) {
+ String pageSource = driver.getPageSource();
+ System.out.println("*** logout pagesouce ***");
+ System.out.println(pageSource);
+ System.out.println("driver url: " + driver.getCurrentUrl());
+ Assert.assertTrue(pageSource.contains("request-path: /logout.jsp"));
+ driver.navigate().to(mainUrl);
+ Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
}
@@ -94,7 +100,7 @@ public class SamlBindingTest {
System.out.println(driver.getPageSource());
Assert.assertTrue(driver.getPageSource().contains("bburke"));
driver.navigate().to("http://localhost:8081/sales-post?GLO=true");
- checkLoggedOut();
+ checkLoggedOut("http://localhost:8081/sales-post/");
}
@Test
public void testPostSignedLoginLogout() {
@@ -104,7 +110,7 @@ public class SamlBindingTest {
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig/");
Assert.assertTrue(driver.getPageSource().contains("bburke"));
driver.navigate().to("http://localhost:8081/sales-post-sig?GLO=true");
- checkLoggedOut();
+ checkLoggedOut("http://localhost:8081/sales-post-sig/");
}
@Test
@@ -117,7 +123,7 @@ public class SamlBindingTest {
Assert.assertFalse(driver.getPageSource().contains("bburke"));
Assert.assertTrue(driver.getPageSource().contains("principal=G-"));
driver.navigate().to("http://localhost:8081/sales-post-sig-transient?GLO=true");
- checkLoggedOut();
+ checkLoggedOut("http://localhost:8081/sales-post-sig-transient/");
}
@Test
@@ -130,7 +136,7 @@ public class SamlBindingTest {
Assert.assertFalse(driver.getPageSource().contains("bburke"));
Assert.assertTrue(driver.getPageSource().contains("principal=G-"));
driver.navigate().to("http://localhost:8081/sales-post-sig-persistent?GLO=true");
- checkLoggedOut();
+ checkLoggedOut("http://localhost:8081/sales-post-sig-persistent/");
}
@Test
@@ -142,7 +148,7 @@ public class SamlBindingTest {
System.out.println(driver.getPageSource());
Assert.assertTrue(driver.getPageSource().contains("principal=bburke@redhat.com"));
driver.navigate().to("http://localhost:8081/sales-post-sig-email?GLO=true");
- checkLoggedOut();
+ checkLoggedOut("http://localhost:8081/sales-post-sig-email/");
}
@Test
@@ -153,7 +159,45 @@ public class SamlBindingTest {
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee-sig/");
Assert.assertTrue(driver.getPageSource().contains("bburke"));
driver.navigate().to("http://localhost:8081/employee-sig?GLO=true");
- checkLoggedOut();
+ checkLoggedOut("http://localhost:8081/employee-sig/");
+
+ }
+
+ @Test
+ public void testRedirectSignedLoginLogoutFrontNoSSO() {
+ driver.navigate().to("http://localhost:8081/employee-sig-front/");
+ Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
+ loginPage.login("bburke", "password");
+ Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee-sig-front/");
+ Assert.assertTrue(driver.getPageSource().contains("bburke"));
+ driver.navigate().to("http://localhost:8081/employee-sig-front?GLO=true");
+ checkLoggedOut("http://localhost:8081/employee-sig-front/");
+
+ }
+
+ @Test
+ public void testRedirectSignedLoginLogoutFront() {
+ // visit 1st app an logg in
+ System.out.println("visit 1st app ");
+ driver.navigate().to("http://localhost:8081/employee-sig/");
+ Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
+ System.out.println("login to form");
+ loginPage.login("bburke", "password");
+ Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee-sig/");
+ Assert.assertTrue(driver.getPageSource().contains("bburke"));
+
+ // visit 2nd app
+ System.out.println("visit 2nd app ");
+ driver.navigate().to("http://localhost:8081/employee-sig-front/");
+ Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee-sig-front/");
+ Assert.assertTrue(driver.getPageSource().contains("bburke"));
+
+ // logout of first app
+ System.out.println("GLO");
+ driver.navigate().to("http://localhost:8081/employee-sig?GLO=true");
+ checkLoggedOut("http://localhost:8081/employee-sig/");
+ driver.navigate().to("http://localhost:8081/employee-sig-front/");
+ Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
}
@@ -165,7 +209,7 @@ public class SamlBindingTest {
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-enc/");
Assert.assertTrue(driver.getPageSource().contains("bburke"));
driver.navigate().to("http://localhost:8081/sales-post-enc?GLO=true");
- checkLoggedOut();
+ checkLoggedOut("http://localhost:8081/sales-post-enc/");
}
@Test
@@ -213,7 +257,7 @@ public class SamlBindingTest {
String pageSource = driver.getPageSource();
Assert.assertTrue(pageSource.contains("bburke"));
driver.navigate().to("http://localhost:8081/sales-metadata?GLO=true");
- checkLoggedOut();
+ checkLoggedOut("http://localhost:8081/sales-metadata/");
}
diff --git a/testsuite/integration/src/test/resources/saml/signed-front-get/WEB-INF/keystore.jks b/testsuite/integration/src/test/resources/saml/signed-front-get/WEB-INF/keystore.jks
new file mode 100755
index 0000000..4daad21
Binary files /dev/null and b/testsuite/integration/src/test/resources/saml/signed-front-get/WEB-INF/keystore.jks differ
diff --git a/testsuite/integration/src/test/resources/saml/signed-front-get/WEB-INF/picketlink.xml b/testsuite/integration/src/test/resources/saml/signed-front-get/WEB-INF/picketlink.xml
new file mode 100755
index 0000000..06fff8c
--- /dev/null
+++ b/testsuite/integration/src/test/resources/saml/signed-front-get/WEB-INF/picketlink.xml
@@ -0,0 +1,38 @@
+<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1">
+ <PicketLinkSP xmlns="urn:picketlink:identity-federation:config:2.1"
+ ServerEnvironment="tomcat" BindingType="REDIRECT" SupportsSignatures="true" LogOutResponseLocation="${idp-sig.url::http://localhost:8081/auth/realms/demo/protocol/saml}">
+ <IdentityURL>${idp-sig.url::http://localhost:8081/auth/realms/demo/protocol/saml}
+ </IdentityURL>
+ <ServiceURL>${employee-sig.url::http://localhost:8081/employee-sig-front/}
+ </ServiceURL>
+ <KeyProvider
+ ClassName="org.picketlink.identity.federation.core.impl.KeyStoreKeyManager">
+ <Auth Key="KeyStoreURL" Value="saml/signed-front-get/WEB-INF/keystore.jks" />
+ <Auth Key="KeyStorePass" Value="store123" />
+ <Auth Key="SigningKeyPass" Value="test123" />
+ <Auth Key="SigningKeyAlias" Value="http://localhost:8080/employee-sig/" />
+ <ValidatingAlias Key="localhost" Value="demo" />
+ <ValidatingAlias Key="127.0.0.1" Value="demo" />
+ </KeyProvider>
+ </PicketLinkSP>
+ <Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1">
+ <Handler
+ class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" />
+ <Handler
+ class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler">
+ <Option Key="NAMEID_FORMAT" Value="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"/>
+ </Handler>
+ <Handler
+ class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler" />
+ <Handler
+ class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureGenerationHandler">
+ <!--
+ This is a optional configuration. By default, method http://www.w3.org/2000/09/xmldsig#rsa-sha1
+ and digest http://www.w3.org/2000/09/xmldsig#sha1 are used. -->
+ <Option Key="SIGN_METHOD" Value="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
+ <Option Key="SIGN_DIGEST" Value="http://www.w3.org/2001/04/xmlenc#sha256"/>
+ </Handler>
+ <Handler
+ class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureValidationHandler" />
+ </Handlers>
+</PicketLink>
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/saml/testsaml.json b/testsuite/integration/src/test/resources/saml/testsaml.json
index 4453c34..0e31188 100755
--- a/testsuite/integration/src/test/resources/saml/testsaml.json
+++ b/testsuite/integration/src/test/resources/saml/testsaml.json
@@ -194,6 +194,26 @@
"saml.signing.private.key": "MIICXQIBAAKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABAoGANU1efgc6ojIvwn7Lsf8GAKN9z2D6uS0T3I9nw1k2CtI+xWhgKAUltEANx5lEfBRYIdYclidRpqrk8DYgzASrDYTHXzqVBJfAk1VrAGpqyRq+TNMLUHkXiTiSDOQ6WqhX93UGMmAgQm1RsLa6+fy1BO/B2y85+Yf2OUylsKS6avECQQDslRDiNFdtEjdvyOL20tQ7+W+eKVxVxKAyQ3gFjIIDizELZt+Jq1Wz6XV9NhK1JFtlVugeD1tlW/+K16fEmDYXAkEAzqKoN/JeGb20rfQldAUWdQbb0jrQAYlgoSU/9fYH9YVJT8vnkfhPBTwIw9H9euf1//lRP/jHltHd5ch4230YyQJBAN3rOkoltPiABPZbpuLGgwS7BwOCYrWlWmurtBLoaTCvyVKbrgXybNL1pBrOtR+rufvGWLeRyja65Gs1vY6BBQMCQQCTsNq/MjJj/522f7yNUl2cw4w2lOa7Um+IflFbAcDqkZu2ty0Kvgns2d4B6INeZ5ECpjaWnMA7YkFRzZnkd2NRAkB8lEY56ScnNigoZkkjtEUd2ejdhZPYuS9SKfv9zHwN+I+DE2vVFZz8GPq/iLcMx13PkZaYaJNQ4FtQY/hRLSn5",
"saml.signing.certificate": "MIIB0DCCATkCBgFJH5u0EDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNodHRwOi8vbG9jYWxob3N0OjgwODAvZW1wbG95ZWUtc2lnLzAeFw0xNDEwMTcxOTMzNThaFw0yNDEwMTcxOTM1MzhaMC4xLDAqBgNVBAMTI2h0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9lbXBsb3llZS1zaWcvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACKyPLGqMX8GsIrCfJU8eVnpaqzTXMglLVo/nTcfAnWe9UAdVe8N3a2PXpDBvuqNA/DEAhVcQgxdlOTWnB6s8/yLTRuH0bZgb3qGdySif+lU+E7zZ/SiDzavAvn+ABqemnzHcHyhYO+hNRGHvUbW5OAii9Vdjhm8BI32YF1NwhKp"
}
+ },
+ {
+ "name": "http://localhost:8081/employee-sig-front/",
+ "enabled": true,
+ "protocol": "saml",
+ "fullScopeAllowed": true,
+ "frontchannelLogout": true,
+ "baseUrl": "http://localhost:8081/employee-sig-front",
+ "adminUrl": "http://localhost:8081/employee-sig-front",
+ "redirectUris": [
+ "http://localhost:8081/employee-sig-front/*"
+ ],
+ "attributes": {
+ "saml.server.signature": "true",
+ "saml.client.signature": "true",
+ "saml.signature.algorithm": "RSA_SHA1",
+ "saml.authnstatement": "true",
+ "saml.signing.private.key": "MIICXQIBAAKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABAoGANU1efgc6ojIvwn7Lsf8GAKN9z2D6uS0T3I9nw1k2CtI+xWhgKAUltEANx5lEfBRYIdYclidRpqrk8DYgzASrDYTHXzqVBJfAk1VrAGpqyRq+TNMLUHkXiTiSDOQ6WqhX93UGMmAgQm1RsLa6+fy1BO/B2y85+Yf2OUylsKS6avECQQDslRDiNFdtEjdvyOL20tQ7+W+eKVxVxKAyQ3gFjIIDizELZt+Jq1Wz6XV9NhK1JFtlVugeD1tlW/+K16fEmDYXAkEAzqKoN/JeGb20rfQldAUWdQbb0jrQAYlgoSU/9fYH9YVJT8vnkfhPBTwIw9H9euf1//lRP/jHltHd5ch4230YyQJBAN3rOkoltPiABPZbpuLGgwS7BwOCYrWlWmurtBLoaTCvyVKbrgXybNL1pBrOtR+rufvGWLeRyja65Gs1vY6BBQMCQQCTsNq/MjJj/522f7yNUl2cw4w2lOa7Um+IflFbAcDqkZu2ty0Kvgns2d4B6INeZ5ECpjaWnMA7YkFRzZnkd2NRAkB8lEY56ScnNigoZkkjtEUd2ejdhZPYuS9SKfv9zHwN+I+DE2vVFZz8GPq/iLcMx13PkZaYaJNQ4FtQY/hRLSn5",
+ "saml.signing.certificate": "MIIB0DCCATkCBgFJH5u0EDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNodHRwOi8vbG9jYWxob3N0OjgwODAvZW1wbG95ZWUtc2lnLzAeFw0xNDEwMTcxOTMzNThaFw0yNDEwMTcxOTM1MzhaMC4xLDAqBgNVBAMTI2h0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9lbXBsb3llZS1zaWcvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACKyPLGqMX8GsIrCfJU8eVnpaqzTXMglLVo/nTcfAnWe9UAdVe8N3a2PXpDBvuqNA/DEAhVcQgxdlOTWnB6s8/yLTRuH0bZgb3qGdySif+lU+E7zZ/SiDzavAvn+ABqemnzHcHyhYO+hNRGHvUbW5OAii9Vdjhm8BI32YF1NwhKp"
+ }
}
],
"roles" : {