keycloak-aplcache
Changes
model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java 5(+4 -1)
model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java 4(+4 -0)
model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/PostgresPlusDatabase.java 56(+56 -0)
testsuite/integration/pom.xml 1(+1 -0)
testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTest.java 5(+5 -0)
Details
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
index ce7ebf1..7a472aa 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
@@ -54,9 +54,12 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
entity.setTimestamp(Time.currentTime());
entity.setClient(client.getId());
+
tx.put(sessionCache, id, entity);
- return wrap(realm, entity, false);
+ ClientSessionAdapter wrap = wrap(realm, entity, false);
+ wrap.setNote(ClientSessionModel.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
+ return wrap;
}
@Override
diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/JpaUpdaterProvider.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/JpaUpdaterProvider.java
index 255bec4..9c44cf4 100755
--- a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/JpaUpdaterProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/JpaUpdaterProvider.java
@@ -12,7 +12,7 @@ public interface JpaUpdaterProvider extends Provider {
public String FIRST_VERSION = "1.0.0.Final";
- public String LAST_VERSION = "1.8.0";
+ public String LAST_VERSION = "1.9.0";
public String getCurrentVersionSql(String defaultSchema);
diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java
index 464e51f..211c00e 100755
--- a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java
@@ -109,6 +109,10 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
}
LogFactory.setInstance(new LogWrapper());
+
+ // Adding PostgresPlus support to liquibase
+ DatabaseFactory.getInstance().register(new PostgresPlusDatabase());
+
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
if (defaultSchema != null) {
database.setDefaultSchemaName(defaultSchema);
diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/PostgresPlusDatabase.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/PostgresPlusDatabase.java
new file mode 100644
index 0000000..ffea018
--- /dev/null
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/PostgresPlusDatabase.java
@@ -0,0 +1,56 @@
+package org.keycloak.connections.jpa.updater.liquibase;
+
+import liquibase.database.DatabaseConnection;
+import liquibase.database.core.PostgresDatabase;
+import liquibase.exception.DatabaseException;
+import liquibase.executor.ExecutorService;
+import liquibase.statement.core.RawSqlStatement;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class PostgresPlusDatabase extends PostgresDatabase {
+
+ public static final String POSTGRESPLUS_PRODUCT_NAME = "EnterpriseDB";
+
+ @Override
+ public String getShortName() {
+ return "postgresplus";
+ }
+
+ @Override
+ protected String getDefaultDatabaseProductName() {
+ return POSTGRESPLUS_PRODUCT_NAME;
+ }
+
+ @Override
+ public boolean isCorrectDatabaseImplementation(DatabaseConnection conn) throws DatabaseException {
+ return POSTGRESPLUS_PRODUCT_NAME.equalsIgnoreCase(conn.getDatabaseProductName());
+ }
+
+ @Override
+ public String getDefaultDriver(String url) {
+ String defaultDriver = super.getDefaultDriver(url);
+
+ if (defaultDriver == null) {
+ if (url.startsWith("jdbc:edb:")) {
+ defaultDriver = "com.edb.Driver";
+ }
+ }
+
+ return defaultDriver;
+ }
+
+ @Override
+ protected String getConnectionSchemaName() {
+ try {
+ String currentSchema = ExecutorService.getInstance().getExecutor(this)
+ .queryForObject(new RawSqlStatement("select current_schema"), String.class);
+ return currentSchema;
+
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to get current schema", e);
+ }
+ }
+
+}
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-1.8.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.8.0.xml
index 12606a3..7bb2f79 100755
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-1.8.0.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.8.0.xml
@@ -119,6 +119,12 @@
<column name="ALGORITHM" type="VARCHAR(36)" value="pbkdf2" />
<where>TYPE in ('password-history', 'password') AND ALGORITHM = 'HmacSHA1'</where>
</update>
+
+ <!-- Sybase specific hacks -->
+ <modifySql dbms="sybase">
+ <regExpReplace replace=".*(SET DEFAULT NULL)" with="SELECT 1" />
+ </modifySql>
+
</changeSet>
</databaseChangeLog>
\ No newline at end of file
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-1.9.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.9.0.xml
new file mode 100644
index 0000000..02c1423
--- /dev/null
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.9.0.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
+ <changeSet author="mposolda@redhat.com" id="1.9.0">
+
+ <!-- This is needed for MSSQL :( -->
+ <!-- 1.5 -->
+ <update tableName="REALM">
+ <column name="OTP_POLICY_COUNTER" type="INT" value="0" />
+ <where>OTP_POLICY_COUNTER is NULL</where>
+ </update>
+ <update tableName="REALM">
+ <column name="OTP_POLICY_WINDOW" type="INT" value="1" />
+ <where>OTP_POLICY_WINDOW is NULL</where>
+ </update>
+ <update tableName="REALM">
+ <column name="OTP_POLICY_PERIOD" type="INT" value="30" />
+ <where>OTP_POLICY_PERIOD is NULL</where>
+ </update>
+ <update tableName="REALM">
+ <column name="OTP_POLICY_DIGITS" type="INT" value="6" />
+ <where>OTP_POLICY_DIGITS is NULL</where>
+ </update>
+ <update tableName="CREDENTIAL">
+ <column name="COUNTER" type="INT" value="0" />
+ <where>COUNTER is NULL</where>
+ </update>
+ <update tableName="CREDENTIAL">
+ <column name="DIGITS" type="INT" value="6" />
+ <where>DIGITS is NULL</where>
+ </update>
+ <update tableName="CREDENTIAL">
+ <column name="PERIOD" type="INT" value="30" />
+ <where>PERIOD is NULL</where>
+ </update>
+ <!-- 1.6 -->
+ <update tableName="REALM">
+ <column name="OFFLINE_SESSION_IDLE_TIMEOUT" type="INT" value="2592000" />
+ <where>OFFLINE_SESSION_IDLE_TIMEOUT is NULL</where>
+ </update>
+ <!-- 1.7 -->
+ <update tableName="REALM">
+ <column name="ACCESS_TOKEN_LIFE_IMPLICIT" type="INT" value="900" />
+ <where>ACCESS_TOKEN_LIFE_IMPLICIT is NULL</where>
+ </update>
+
+ </changeSet>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml
index 0f907e0..987d5e2 100755
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml
@@ -12,4 +12,5 @@
<include file="META-INF/jpa-changelog-1.6.1.xml"/>
<include file="META-INF/jpa-changelog-1.7.0.xml"/>
<include file="META-INF/jpa-changelog-1.8.0.xml"/>
+ <include file="META-INF/jpa-changelog-1.9.0.xml"/>
</databaseChangeLog>
diff --git a/server-spi/src/main/java/org/keycloak/models/ClientSessionModel.java b/server-spi/src/main/java/org/keycloak/models/ClientSessionModel.java
index 293f38b..803473a 100755
--- a/server-spi/src/main/java/org/keycloak/models/ClientSessionModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/ClientSessionModel.java
@@ -7,6 +7,7 @@ import java.util.Set;
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface ClientSessionModel {
+ public static final String ACTION_KEY = "action_key";
public String getId();
public RealmModel getRealm();
diff --git a/server-spi/src/main/java/org/keycloak/models/OTPPolicy.java b/server-spi/src/main/java/org/keycloak/models/OTPPolicy.java
index 8d76bb9..3097acf 100755
--- a/server-spi/src/main/java/org/keycloak/models/OTPPolicy.java
+++ b/server-spi/src/main/java/org/keycloak/models/OTPPolicy.java
@@ -96,25 +96,25 @@ public class OTPPolicy implements Serializable {
}
public String getKeyURI(RealmModel realm, UserModel user, String secret) {
+ try {
+ String displayName = realm.getDisplayName() != null && !realm.getDisplayName().isEmpty() ? realm.getDisplayName() : realm.getName();
+ String uri;
- String displayName = realm.getDisplayName();
- String uri = null;
-
- if (displayName == null || displayName.isEmpty()) { displayName = realm.getName(); }
- uri = "otpauth://" + type + "/" + displayName + ":" + user.getUsername() + "?secret=" +
- Base32.encode(secret.getBytes()) + "&digits=" + digits + "&algorithm=" + algToKeyUriAlg.get(algorithm);
- try {
- uri += "&issuer=" + URLEncoder.encode(realm.getName(), "UTF-8");
- } catch (UnsupportedEncodingException e) {
- logger.debug("Failed to add issuer parameter to OTP URI becasue UTF-8 is not supported.");
- }
- if (type.equals(UserCredentialModel.HOTP)) {
- uri += "&counter=" + initialCounter;
- }
- if (type.equals(UserCredentialModel.TOTP)) {
- uri += "&period=" + period;
- }
- return uri;
+ uri = "otpauth://" + type + "/" + URLEncoder.encode(user.getUsername(), "UTF-8") + "?secret=" +
+ Base32.encode(secret.getBytes()) + "&digits=" + digits + "&algorithm=" + algToKeyUriAlg.get(algorithm);
+
+ uri += "&issuer=" + URLEncoder.encode(displayName, "UTF-8");
+ if (type.equals(UserCredentialModel.HOTP)) {
+ uri += "&counter=" + initialCounter;
+ }
+ if (type.equals(UserCredentialModel.TOTP)) {
+ uri += "&period=" + period;
+ }
+
+ return uri;
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
}
}
diff --git a/server-spi/src/main/java/org/keycloak/services/managers/ClientSessionCode.java b/server-spi/src/main/java/org/keycloak/services/managers/ClientSessionCode.java
index 91c388f..64386ab 100755
--- a/server-spi/src/main/java/org/keycloak/services/managers/ClientSessionCode.java
+++ b/server-spi/src/main/java/org/keycloak/services/managers/ClientSessionCode.java
@@ -22,8 +22,6 @@ import java.util.UUID;
*/
public class ClientSessionCode {
- public static final String ACTION_KEY = "action_key";
-
private static final byte[] HASH_SEPERATOR = "//".getBytes();
private final RealmModel realm;
@@ -211,7 +209,6 @@ public class ClientSessionCode {
public void setAction(String action) {
clientSession.setAction(action);
- clientSession.setNote(ACTION_KEY, UUID.randomUUID().toString());
clientSession.setTimestamp(Time.currentTime());
}
@@ -237,7 +234,7 @@ public class ClientSessionCode {
mac.init(codeSecretKey);
mac.update(clientSession.getId().getBytes());
mac.update(HASH_SEPERATOR);
- mac.update(clientSession.getNote(ACTION_KEY).getBytes());
+ mac.update(clientSession.getNote(ClientSessionModel.ACTION_KEY).getBytes());
return Base64Url.encode(mac.doFinal());
} catch (Exception e) {
throw new RuntimeException(e);
diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
index 184df85..d40b96b 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
@@ -1,5 +1,6 @@
package org.keycloak.authentication;
+import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.common.ClientConnection;
import org.keycloak.OAuth2Constants;
@@ -30,6 +31,7 @@ import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.LoginActionsService;
import org.keycloak.common.util.Time;
+import org.keycloak.services.util.CacheControlUtil;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
@@ -575,9 +577,11 @@ public class AuthenticationProcessor {
.setConnection(connection)
.setEventBuilder(event)
.setRealm(realm)
+ .setBrowserFlow(isBrowserFlow())
.setSession(session)
.setUriInfo(uriInfo)
.setRequest(request);
+ CacheControlUtil.noBackButtonCacheControlHeader();
return processor.authenticate();
} else {
@@ -656,6 +660,17 @@ public class AuthenticationProcessor {
}
}
+
+ public Response redirectToFlow() {
+ String code = generateCode();
+
+ URI redirect = LoginActionsService.loginActionsBaseUrl(getUriInfo())
+ .path(flowPath)
+ .queryParam(OAuth2Constants.CODE, code).build(getRealm().getName());
+ return Response.status(302).location(redirect).build();
+
+ }
+
public static Response redirectToRequiredActions(RealmModel realm, ClientSessionModel clientSession, UriInfo uriInfo) {
// redirect to non-action url so browser refresh button works without reposting past data
diff --git a/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java b/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
index 1b2e871..2ae084f 100755
--- a/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
+++ b/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
@@ -74,9 +74,10 @@ public abstract class AuthorizationEndpointBase {
* @param clientSession for current request
* @param protocol handler for protocol used to initiate login
* @param isPassive set to true if login should be passive (without login screen shown)
+ * @param redirectToAuthentication if true redirect to flow url. If initial call to protocol is a POST, you probably want to do this. This is so we can disable the back button on browser
* @return response to be returned to the browser
*/
- protected Response handleBrowserAuthenticationRequest(ClientSessionModel clientSession, LoginProtocol protocol, boolean isPassive) {
+ protected Response handleBrowserAuthenticationRequest(ClientSessionModel clientSession, LoginProtocol protocol, boolean isPassive, boolean redirectToAuthentication) {
List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
for (IdentityProviderModel identityProvider : identityProviders) {
@@ -115,6 +116,9 @@ public abstract class AuthorizationEndpointBase {
} else {
try {
RestartLoginCookie.setRestartCookie(realm, clientConnection, uriInfo, clientSession);
+ if (redirectToAuthentication) {
+ return processor.redirectToFlow();
+ }
return processor.authenticate();
} catch (Exception e) {
return processor.handleBrowserException(e);
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
old mode 100644
new mode 100755
index 61db4f1..f4dd22a
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
@@ -28,6 +28,7 @@ import org.keycloak.services.Urls;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.LoginActionsService;
+import org.keycloak.services.util.CacheControlUtil;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -87,7 +88,8 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
checkRedirectUri();
createClientSession();
-
+ // So back button doesn't work
+ CacheControlUtil.noBackButtonCacheControlHeader();
switch (action) {
case REGISTER:
return buildRegister();
@@ -219,7 +221,6 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL);
clientSession.setRedirectUri(redirectUri);
clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
- clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
clientSession.setNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM, responseType);
clientSession.setNote(OIDCLoginProtocol.REDIRECT_URI_PARAM, redirectUriParam);
clientSession.setNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
@@ -249,7 +250,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
this.event.event(EventType.LOGIN);
clientSession.setNote(Details.AUTH_TYPE, CODE_AUTH_TYPE);
- return handleBrowserAuthenticationRequest(clientSession, new OIDCLoginProtocol(session, realm, uriInfo, headers, event), prompt != null && prompt.equals("none"));
+ return handleBrowserAuthenticationRequest(clientSession, new OIDCLoginProtocol(session, realm, uriInfo, headers, event), prompt != null && prompt.equals("none"), false);
}
private Response buildRegister() {
diff --git a/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java b/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java
index 2885f38..7d30170 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java
@@ -68,8 +68,8 @@ public class SamlEcpProfileService extends SamlService {
}
@Override
- protected Response newBrowserAuthentication(ClientSessionModel clientSession, boolean isPassive, SamlProtocol samlProtocol) {
- return super.newBrowserAuthentication(clientSession, isPassive, createEcpSamlProtocol());
+ protected Response newBrowserAuthentication(ClientSessionModel clientSession, boolean isPassive, boolean redirectToAuthentication, SamlProtocol samlProtocol) {
+ return super.newBrowserAuthentication(clientSession, isPassive, redirectToAuthentication, createEcpSamlProtocol());
}
private SamlProtocol createEcpSamlProtocol() {
diff --git a/services/src/main/java/org/keycloak/protocol/saml/SamlService.java b/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
index 0260fc7..566cf87 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
@@ -18,6 +18,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.jboss.logging.Logger;
+import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.common.VerificationException;
import org.keycloak.common.util.StreamUtil;
@@ -50,6 +51,7 @@ import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.RealmsResource;
+import org.keycloak.services.util.CacheControlUtil;
/**
* Resource class for the oauth/openid connect token service
@@ -66,6 +68,12 @@ public class SamlService extends AuthorizationEndpointBase {
}
public abstract class BindingProtocol {
+
+ // this is to support back button on browser
+ // if true, we redirect to authenticate URL otherwise back button behavior has bad side effects
+ // and we want to turn it off.
+ protected boolean redirectToAuthentication;
+
protected Response basicChecks(String samlRequest, String samlResponse) {
if (!checkSsl()) {
event.event(EventType.LOGIN);
@@ -229,7 +237,6 @@ public class SamlService extends AuthorizationEndpointBase {
clientSession.setAuthMethod(SamlProtocol.LOGIN_PROTOCOL);
clientSession.setRedirectUri(redirect);
clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
- clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
clientSession.setNote(SamlProtocol.SAML_BINDING, bindingType);
clientSession.setNote(GeneralConstants.RELAY_STATE, relayState);
clientSession.setNote(SamlProtocol.SAML_REQUEST_ID, requestAbstractType.getID());
@@ -248,7 +255,7 @@ public class SamlService extends AuthorizationEndpointBase {
}
}
- return newBrowserAuthentication(clientSession, requestAbstractType.isIsPassive());
+ return newBrowserAuthentication(clientSession, requestAbstractType.isIsPassive(), redirectToAuthentication);
}
protected String getBindingType(AuthnRequestType requestAbstractType) {
@@ -449,13 +456,13 @@ public class SamlService extends AuthorizationEndpointBase {
}
- protected Response newBrowserAuthentication(ClientSessionModel clientSession, boolean isPassive) {
+ protected Response newBrowserAuthentication(ClientSessionModel clientSession, boolean isPassive, boolean redirectToAuthentication) {
SamlProtocol samlProtocol = new SamlProtocol().setEventBuilder(event).setHttpHeaders(headers).setRealm(realm).setSession(session).setUriInfo(uriInfo);
- return newBrowserAuthentication(clientSession, isPassive, samlProtocol);
+ return newBrowserAuthentication(clientSession, isPassive, redirectToAuthentication, samlProtocol);
}
- protected Response newBrowserAuthentication(ClientSessionModel clientSession, boolean isPassive, SamlProtocol samlProtocol) {
- return handleBrowserAuthenticationRequest(clientSession, samlProtocol, isPassive);
+ protected Response newBrowserAuthentication(ClientSessionModel clientSession, boolean isPassive, boolean redirectToAuthentication, SamlProtocol samlProtocol) {
+ return handleBrowserAuthenticationRequest(clientSession, samlProtocol, isPassive, redirectToAuthentication);
}
/**
@@ -463,21 +470,29 @@ public class SamlService extends AuthorizationEndpointBase {
@GET
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");
+ CacheControlUtil.noBackButtonCacheControlHeader();
return new RedirectBindingProtocol().execute(samlRequest, samlResponse, relayState);
}
/**
*/
@POST
+ @NoCache
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
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);
+ PostBindingProtocol postBindingProtocol = new PostBindingProtocol();
+ // this is to support back button on browser
+ // if true, we redirect to authenticate URL otherwise back button behavior has bad side effects
+ // and we want to turn it off.
+ postBindingProtocol.redirectToAuthentication = true;
+ return postBindingProtocol.execute(samlRequest, samlResponse, relayState);
}
@GET
@Path("descriptor")
@Produces(MediaType.APPLICATION_XML)
+ @NoCache
public String getDescriptor() throws Exception {
return getIDPMetadataDescriptor(uriInfo, realm);
@@ -499,6 +514,7 @@ public class SamlService extends AuthorizationEndpointBase {
@Produces(MediaType.TEXT_HTML)
public Response idpInitiatedSSO(@PathParam("client") String clientUrlName, @QueryParam("RelayState") String relayState) {
event.event(EventType.LOGIN);
+ CacheControlUtil.noBackButtonCacheControlHeader();
ClientModel client = null;
for (ClientModel c : realm.getClients()) {
String urlName = c.getAttribute(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME);
@@ -537,7 +553,6 @@ public class SamlService extends AuthorizationEndpointBase {
ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
clientSession.setAuthMethod(SamlProtocol.LOGIN_PROTOCOL);
clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
- clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
clientSession.setNote(SamlProtocol.SAML_BINDING, SamlProtocol.SAML_POST_BINDING);
clientSession.setNote(SamlProtocol.SAML_IDP_INITIATED_LOGIN, "true");
clientSession.setRedirectUri(redirect);
@@ -549,11 +564,12 @@ public class SamlService extends AuthorizationEndpointBase {
clientSession.setNote(GeneralConstants.RELAY_STATE, relayState);
}
- return newBrowserAuthentication(clientSession, false);
+ return newBrowserAuthentication(clientSession, false, false);
}
@POST
+ @NoCache
@Consumes({"application/soap+xml",MediaType.TEXT_XML})
public Response soapBinding(InputStream inputStream) {
SamlEcpProfileService bindingService = new SamlEcpProfileService(realm, event);
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 0f9a124..bb7aae3 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -528,7 +528,8 @@ public class AuthenticationManager {
// Skip grant screen if everything was already approved by this user
if (realmRoles.size() > 0 || resourceRoles.size() > 0 || protocolMappers.size() > 0) {
- accessCode.setAction(ClientSessionModel.Action.OAUTH_GRANT.name());
+ accessCode.setAction(ClientSessionModel.Action.REQUIRED_ACTIONS.name());
+ clientSession.setNote(CURRENT_REQUIRED_ACTION, ClientSessionModel.Action.OAUTH_GRANT.name());
return session.getProvider(LoginFormsProvider.class)
.setClientSessionCode(accessCode.getCode())
diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
old mode 100644
new mode 100755
index 937df16..f19151a
--- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
+++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
@@ -17,6 +17,7 @@
*/
package org.keycloak.services.resources;
+import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.OAuth2Constants;
@@ -61,6 +62,7 @@ import org.keycloak.services.ErrorResponse;
import org.keycloak.services.ErrorPage;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.Urls;
+import org.keycloak.services.util.CacheControlUtil;
import org.keycloak.services.validation.Validation;
import org.keycloak.broker.social.SocialIdentityProvider;
import org.keycloak.common.util.ObjectUtil;
@@ -694,6 +696,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
processor.setClientSession(clientSession)
.setFlowPath(LoginActionsService.AUTHENTICATE_PATH)
.setFlowId(flowId)
+ .setBrowserFlow(true)
.setConnection(clientConnection)
.setEventBuilder(event)
.setRealm(realmModel)
@@ -703,6 +706,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
if (errorMessage != null) processor.setForwardedErrorMessage(new FormMessage(null, errorMessage));
try {
+ CacheControlUtil.noBackButtonCacheControlHeader();
return processor.authenticate();
} catch (Exception e) {
return processor.handleBrowserException(e);
diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
index e23f9df..969fa8e 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -67,6 +67,7 @@ import org.keycloak.services.Urls;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
+import org.keycloak.services.util.CacheControlUtil;
import org.keycloak.services.util.CookieHelper;
import javax.ws.rs.Consumes;
@@ -155,6 +156,7 @@ public class LoginActionsService {
public LoginActionsService(RealmModel realm, EventBuilder event) {
this.realm = realm;
this.event = event;
+ CacheControlUtil.noBackButtonCacheControlHeader();
}
private boolean checkSsl() {
@@ -175,20 +177,34 @@ public class LoginActionsService {
if (!verifyCode(code)) {
return false;
}
- if (!verifyAction(requiredAction, actionType)) {
- return false;
- } else {
- return true;
+ if (!clientCode.isValidAction(requiredAction)) {
+ if (ClientSessionModel.Action.REQUIRED_ACTIONS.name().equals(clientCode.getClientSession().getAction())) {
+ response = redirectToRequiredActions(code);
+ return false;
+ } else {
+ invalidAction();
+ return false;
+ }
}
- }
+ if (!isActionActive(actionType)) return false;
+ return true;
+ }
- public boolean verifyAction(String requiredAction, ClientSessionCode.ActionType actionType) {
+ public boolean isValidAction(String requiredAction) {
if (!clientCode.isValidAction(requiredAction)) {
- event.client(clientCode.getClientSession().getClient());
- event.error(Errors.INVALID_CODE);
- response = ErrorPage.error(session, Messages.INVALID_CODE);
+ invalidAction();
return false;
}
+ return true;
+ }
+
+ private void invalidAction() {
+ event.client(clientCode.getClientSession().getClient());
+ event.error(Errors.INVALID_CODE);
+ response = ErrorPage.error(session, Messages.INVALID_CODE);
+ }
+
+ public boolean isActionActive(ClientSessionCode.ActionType actionType) {
if (!clientCode.isActionActive(actionType)) {
event.client(clientCode.getClientSession().getClient());
event.clone().error(Errors.EXPIRED_CODE);
@@ -256,8 +272,48 @@ public class LoginActionsService {
session.getContext().setClient(client);
return true;
}
+
+ public boolean verifyRequiredAction(String code, String executedAction) {
+ if (!verifyCode(code)) {
+ return false;
+ }
+ if (!isValidAction(ClientSessionModel.Action.REQUIRED_ACTIONS.name())) return false;
+ if (!isActionActive(ClientSessionCode.ActionType.USER)) return false;
+
+ final ClientSessionModel clientSession = clientCode.getClientSession();
+
+ final UserSessionModel userSession = clientSession.getUserSession();
+ if (userSession == null) {
+ logger.userSessionNull();
+ event.error(Errors.USER_SESSION_NOT_FOUND);
+ throw new WebApplicationException(ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE));
+ }
+ if (!AuthenticationManager.isSessionValid(realm, userSession)) {
+ AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, true);
+ event.error(Errors.INVALID_CODE);
+ response = ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
+ return false;
+ }
+
+ if (executedAction == null && userSession != null) { // do next required action only if user is already authenticated
+ initEvent(clientSession);
+ event.event(EventType.LOGIN);
+ response = AuthenticationManager.nextActionAfterAuthentication(session, userSession, clientSession, clientConnection, request, uriInfo, event);
+ return false;
+ }
+
+ if (!executedAction.equals(clientSession.getNote(AuthenticationManager.CURRENT_REQUIRED_ACTION))) {
+ logger.debug("required action doesn't match current required action");
+ clientSession.removeNote(AuthenticationManager.CURRENT_REQUIRED_ACTION);
+ response = redirectToRequiredActions(code);
+ return false;
+ }
+ return true;
+
+ }
}
+
/**
* protocol independent login page entry point
*
@@ -361,13 +417,11 @@ public class LoginActionsService {
ClientModel client = realm.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
- clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
//clientSession.setNote(AuthenticationManager.END_AFTER_REQUIRED_ACTIONS, "true");
clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL);
String redirectUri = Urls.accountBase(uriInfo.getBaseUri()).path("/").build(realm.getName()).toString();
clientSession.setRedirectUri(redirectUri);
clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
- clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
clientSession.setNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM, OAuth2Constants.CODE);
clientSession.setNote(OIDCLoginProtocol.REDIRECT_URI_PARAM, redirectUri);
clientSession.setNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
@@ -589,19 +643,12 @@ public class LoginActionsService {
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processConsent(final MultivaluedMap<String, String> formData) {
event.event(EventType.LOGIN);
-
-
- if (!checkSsl()) {
- return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
- }
-
String code = formData.getFirst("code");
-
- ClientSessionCode accessCode = ClientSessionCode.parse(code, session, realm);
- if (accessCode == null || !accessCode.isValid(ClientSessionModel.Action.OAUTH_GRANT.name(), ClientSessionCode.ActionType.LOGIN)) {
- event.error(Errors.INVALID_CODE);
- return ErrorPage.error(session, Messages.INVALID_ACCESS_CODE);
+ Checks checks = new Checks();
+ if (!checks.verifyRequiredAction(code, ClientSessionModel.Action.OAUTH_GRANT.name())) {
+ return checks.response;
}
+ ClientSessionCode accessCode = checks.clientCode;
ClientSessionModel clientSession = accessCode.getClientSession();
initEvent(clientSession);
@@ -610,11 +657,6 @@ public class LoginActionsService {
UserModel user = userSession.getUser();
ClientModel client = clientSession.getClient();
- if (!AuthenticationManager.isSessionValid(realm, userSession)) {
- AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, true);
- event.error(Errors.INVALID_CODE);
- return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
- }
if (formData.containsKey("cancel")) {
LoginProtocol protocol = session.getProvider(LoginProtocol.class, clientSession.getAuthMethod());
@@ -810,29 +852,13 @@ public class LoginActionsService {
event.event(EventType.CUSTOM_REQUIRED_ACTION);
event.detail(Details.CUSTOM_REQUIRED_ACTION, action);
Checks checks = new Checks();
- if (!checks.verifyCode(code, ClientSessionModel.Action.REQUIRED_ACTIONS.name(), ClientSessionCode.ActionType.USER)) {
+ if (!checks.verifyRequiredAction(code, action)) {
return checks.response;
}
final ClientSessionCode clientCode = checks.clientCode;
final ClientSessionModel clientSession = clientCode.getClientSession();
final UserSessionModel userSession = clientSession.getUserSession();
- if (userSession == null) {
- logger.userSessionNull();
- event.error(Errors.USER_SESSION_NOT_FOUND);
- throw new WebApplicationException(ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE));
- }
- if (action == null && userSession != null) { // do next required action only if user is already authenticated
- initEvent(clientSession);
- event.event(EventType.LOGIN);
- return AuthenticationManager.nextActionAfterAuthentication(session, userSession, clientSession, clientConnection, request, uriInfo, event);
- }
-
- if (!action.equals(clientSession.getNote(AuthenticationManager.CURRENT_REQUIRED_ACTION))) {
- logger.debug("required action doesn't match current required action");
- clientSession.removeNote(AuthenticationManager.CURRENT_REQUIRED_ACTION);
- redirectToRequiredActions(code);
- }
RequiredActionFactory factory = (RequiredActionFactory)session.getKeycloakSessionFactory().getProviderFactory(RequiredActionProvider.class, action);
if (factory == null) {
diff --git a/services/src/main/java/org/keycloak/services/util/CacheControlUtil.java b/services/src/main/java/org/keycloak/services/util/CacheControlUtil.java
old mode 100644
new mode 100755
index 0e2f1e0..3c9199d
--- a/services/src/main/java/org/keycloak/services/util/CacheControlUtil.java
+++ b/services/src/main/java/org/keycloak/services/util/CacheControlUtil.java
@@ -1,5 +1,7 @@
package org.keycloak.services.util;
+import org.jboss.resteasy.spi.HttpResponse;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.Config;
import javax.ws.rs.core.CacheControl;
@@ -9,6 +11,11 @@ import javax.ws.rs.core.CacheControl;
*/
public class CacheControlUtil {
+ public static void noBackButtonCacheControlHeader() {
+ HttpResponse response = ResteasyProviderFactory.getContextData(HttpResponse.class);
+ response.getOutputHeaders().putSingle("Cache-Control", "no-store, must-revalidate, max-age=0");
+ }
+
public static CacheControl getDefaultCacheControl() {
CacheControl cacheControl = new CacheControl();
cacheControl.setNoTransform(false);
testsuite/integration/pom.xml 1(+1 -0)
diff --git a/testsuite/integration/pom.xml b/testsuite/integration/pom.xml
index 20f0387..83596c4 100755
--- a/testsuite/integration/pom.xml
+++ b/testsuite/integration/pom.xml
@@ -502,6 +502,7 @@
<password>${keycloak.connectionsJpa.password}</password>
<promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
+ <databaseClass>${keycloak.connectionsJpa.liquibaseDatabaseClass}</databaseClass>
</configuration>
<executions>
<execution>
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 fb1fa58..c4acbd2 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
@@ -54,6 +54,11 @@ public class SamlAdapterTest {
@Rule
public SamlAdapterTestStrategy testStrategy = new SamlAdapterTestStrategy("http://localhost:8081/auth", "http://localhost:8081", keycloakRule);
+ //@Test
+ public void testIDE() throws Exception {
+ Thread.sleep(100000000);
+ }
+
@Test
public void testPostBadRealmSignature() {
testStrategy.testPostBadRealmSignature();
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 9f07239..43c8189 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
@@ -99,15 +99,27 @@ public class SamlAdapterTestStrategy extends ExternalResource {
- protected void checkLoggedOut(String mainUrl) {
+ protected void checkLoggedOut(String mainUrl, boolean postBinding) {
String pageSource = driver.getPageSource();
System.out.println("*** logout pagesource ***");
System.out.println(pageSource);
System.out.println("driver url: " + driver.getCurrentUrl());
Assert.assertTrue(pageSource.contains("request-path: /logout.jsp"));
driver.navigate().to(mainUrl);
+ checkAtLoginPage(postBinding);
+ }
+
+ protected void checkAtLoginPage(boolean postBinding) {
+ if (postBinding) assertAtLoginPagePostBinding();
+ else assertAtLoginPageRedirectBinding();
+ }
+
+ protected void assertAtLoginPageRedirectBinding() {
Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
}
+ protected void assertAtLoginPagePostBinding() {
+ Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/login-actions/authenticate"));
+ }
public void testSavedPostRequest() throws Exception {
// test login to customer-portal which does a bearer request to customer-db
@@ -116,7 +128,7 @@ public class SamlAdapterTestStrategy extends ExternalResource {
Assert.assertTrue(driver.getCurrentUrl().startsWith(APP_SERVER_BASE_URL + "/input-portal"));
inputPage.execute("hello");
- assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertAtLoginPagePostBinding();
loginPage.login("bburke@redhat.com", "password");
System.out.println("Current url: " + driver.getCurrentUrl());
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/input-portal/secured/post");
@@ -170,13 +182,13 @@ public class SamlAdapterTestStrategy extends ExternalResource {
public void testPostSimpleLoginLogout() {
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post/");
- assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertAtLoginPagePostBinding();
loginPage.login("bburke", "password");
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");
- checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post/");
+ checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post/", true);
}
public void testPostPassiveLoginLogout(boolean forbiddenIfNotauthenticated) {
@@ -213,7 +225,7 @@ public class SamlAdapterTestStrategy extends ExternalResource {
public void testPostSimpleUnauthorized(CheckAuthError error) {
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post/");
- assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertAtLoginPagePostBinding();
loginPage.login("unauthorized", "password");
assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post/");
System.out.println(driver.getPageSource());
@@ -227,52 +239,52 @@ public class SamlAdapterTestStrategy extends ExternalResource {
System.out.println(driver.getPageSource());
Assert.assertTrue(driver.getPageSource().contains("bburke"));
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post?GLO=true");
- checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post/");
+ checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post/", true);
}
public void testPostSignedLoginLogout() {
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig/");
- assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertAtLoginPagePostBinding();
loginPage.login("bburke", "password");
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/");
+ checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig/", true);
}
public void testPostSignedLoginLogoutTransientNameID() {
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-transient/");
- assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertAtLoginPagePostBinding();
loginPage.login("bburke", "password");
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-"));
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-transient?GLO=true");
- checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig-transient/");
+ checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig-transient/", true);
}
public void testPostSignedLoginLogoutPersistentNameID() {
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-persistent/");
- assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertAtLoginPagePostBinding();
loginPage.login("bburke", "password");
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-"));
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-persistent?GLO=true");
- checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig-persistent/");
+ checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig-persistent/", true);
}
public void testPostSignedLoginLogoutEmailNameID() {
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-email/");
- assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertAtLoginPagePostBinding();
loginPage.login("bburke", "password");
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");
- checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig-email/");
+ checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig-email/", true);
}
@@ -281,7 +293,7 @@ public class SamlAdapterTestStrategy extends ExternalResource {
// at the relay state
SamlSPFacade.samlResponse = null;
driver.navigate().to(APP_SERVER_BASE_URL + "/employee/");
- Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
+ assertAtLoginPageRedirectBinding();
System.out.println(driver.getCurrentUrl());
loginPage.login("bburke", "password");
assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee/");
@@ -304,7 +316,7 @@ public class SamlAdapterTestStrategy extends ExternalResource {
SendUsernameServlet.sentPrincipal = null;
SendUsernameServlet.checkRoles = null;
driver.navigate().to(APP_SERVER_BASE_URL + "/employee2/");
- Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
+ assertAtLoginPagePostBinding();
List<String> requiredRoles = new LinkedList<>();
requiredRoles.add("manager");
requiredRoles.add("user");
@@ -322,14 +334,14 @@ public class SamlAdapterTestStrategy extends ExternalResource {
Set<String> groupSet = new HashSet<>();
assertEquals("level2@redhat.com", principal.getFriendlyAttribute("email"));
driver.navigate().to(APP_SERVER_BASE_URL + "/employee2/?GLO=true");
- checkLoggedOut(APP_SERVER_BASE_URL + "/employee2/");
+ checkLoggedOut(APP_SERVER_BASE_URL + "/employee2/", true);
}
{
SendUsernameServlet.sentPrincipal = null;
SendUsernameServlet.checkRoles = null;
driver.navigate().to(APP_SERVER_BASE_URL + "/employee2/");
- Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
+ assertAtLoginPagePostBinding();
List<String> requiredRoles = new LinkedList<>();
requiredRoles.add("manager");
requiredRoles.add("employee");
@@ -345,7 +357,7 @@ public class SamlAdapterTestStrategy extends ExternalResource {
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/");
+ checkLoggedOut(APP_SERVER_BASE_URL + "/employee2/", true);
}
keycloakRule.update(new KeycloakRule.KeycloakSetup() {
@@ -374,7 +386,7 @@ public class SamlAdapterTestStrategy extends ExternalResource {
SendUsernameServlet.sentPrincipal = null;
SendUsernameServlet.checkRoles = null;
driver.navigate().to(APP_SERVER_BASE_URL + "/employee2/");
- Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
+ assertAtLoginPagePostBinding();
List<String> requiredRoles = new LinkedList<>();
requiredRoles.add("el-jefe");
requiredRoles.add("user");
@@ -394,23 +406,23 @@ public class SamlAdapterTestStrategy extends ExternalResource {
public void testRedirectSignedLoginLogout() {
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig/");
- Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
+ assertAtLoginPageRedirectBinding();
loginPage.login("bburke", "password");
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/");
+ checkLoggedOut(APP_SERVER_BASE_URL + "/employee-sig/", false);
}
public void testRedirectSignedLoginLogoutFrontNoSSO() {
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig-front/");
- Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
+ assertAtLoginPageRedirectBinding();
loginPage.login("bburke", "password");
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/");
+ checkLoggedOut(APP_SERVER_BASE_URL + "/employee-sig-front/", false);
}
@@ -418,7 +430,7 @@ public class SamlAdapterTestStrategy extends ExternalResource {
// visit 1st app an logg in
System.out.println("visit 1st app ");
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig/");
- Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
+ assertAtLoginPageRedirectBinding();
System.out.println("login to form");
loginPage.login("bburke", "password");
assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee-sig/");
@@ -439,28 +451,29 @@ public class SamlAdapterTestStrategy extends ExternalResource {
// logout of first app
System.out.println("GLO");
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig?GLO=true");
- checkLoggedOut(APP_SERVER_BASE_URL + "/employee-sig/");
+ checkLoggedOut(APP_SERVER_BASE_URL + "/employee-sig/", false);
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig-front/");
String currentUrl = driver.getCurrentUrl();
Assert.assertTrue(currentUrl.startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig/");
- Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
+ assertAtLoginPagePostBinding();
}
public void testPostEncryptedLoginLogout() {
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-enc/");
- assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertAtLoginPagePostBinding();
loginPage.login("bburke", "password");
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/");
+ checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-enc/", true);
}
public void testPostBadClientSignature() {
driver.navigate().to(APP_SERVER_BASE_URL + "/bad-client-sales-post-sig/");
- assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ System.out.println(driver.getCurrentUrl());
+ Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
assertEquals(driver.getTitle(), "We're sorry...");
}
@@ -471,7 +484,7 @@ public class SamlAdapterTestStrategy extends ExternalResource {
public void testPostBadRealmSignature() {
ErrorServlet.authError = null;
driver.navigate().to(APP_SERVER_BASE_URL + "/bad-realm-sales-post-sig/");
- assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertAtLoginPagePostBinding();
loginPage.login("bburke", "password");
assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/bad-realm-sales-post-sig/");
System.out.println(driver.getPageSource());
@@ -484,13 +497,13 @@ public class SamlAdapterTestStrategy extends ExternalResource {
public void testMetadataPostSignedLoginLogout() throws Exception {
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-metadata/");
- assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+ assertAtLoginPagePostBinding();
loginPage.login("bburke", "password");
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");
- checkLoggedOut(APP_SERVER_BASE_URL + "/sales-metadata/");
+ checkLoggedOut(APP_SERVER_BASE_URL + "/sales-metadata/", true);
}