keycloak-uncached
Changes
integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractKeycloakJettyAuthenticator.java 35(+35 -0)
integration/servlet-filter/src/main/java/org/keycloak/adapters/servlet/OIDCFilterSessionStore.java 2(+2 -0)
integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaSessionTokenStore.java 15(+13 -2)
integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletSessionTokenStore.java 4(+3 -1)
integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowSessionTokenStore.java 3(+3 -0)
saml/client-adapter/jetty/jetty-core/src/main/java/org/keycloak/adapters/saml/jetty/AbstractSamlAuthenticator.java 37(+36 -1)
saml/client-adapter/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/saml/AbstractSamlAuthenticatorValve.java 6(+6 -0)
Details
diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractKeycloakJettyAuthenticator.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractKeycloakJettyAuthenticator.java
index dad7570..43f5726 100755
--- a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractKeycloakJettyAuthenticator.java
+++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractKeycloakJettyAuthenticator.java
@@ -1,6 +1,8 @@
package org.keycloak.adapters.jetty.core;
import org.eclipse.jetty.security.DefaultUserIdentity;
+import org.eclipse.jetty.security.IdentityService;
+import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.security.authentication.DeferredAuthentication;
@@ -118,10 +120,43 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
return new DefaultUserIdentity(theSubject, principal, theRoles);
}
+ private class DummyLoginService implements LoginService {
+ @Override
+ public String getName() {
+ return null;
+ }
+
+ @Override
+ public UserIdentity login(String username, Object credentials) {
+ return null;
+ }
+
+ @Override
+ public boolean validate(UserIdentity user) {
+ return false;
+ }
+
+ @Override
+ public IdentityService getIdentityService() {
+ return null;
+ }
+
+ @Override
+ public void setIdentityService(IdentityService service) {
+
+ }
+
+ @Override
+ public void logout(UserIdentity user) {
+
+ }
+ }
@Override
public void setConfiguration(AuthConfiguration configuration) {
//super.setConfiguration(configuration);
initializeKeycloak();
+ // need this so that getUserPrincipal does not throw NPE
+ _loginService = new DummyLoginService();
String error = configuration.getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE);
setErrorPage(error);
}
diff --git a/integration/servlet-filter/src/main/java/org/keycloak/adapters/servlet/OIDCFilterSessionStore.java b/integration/servlet-filter/src/main/java/org/keycloak/adapters/servlet/OIDCFilterSessionStore.java
index 0fa30dc..9909fd0 100755
--- a/integration/servlet-filter/src/main/java/org/keycloak/adapters/servlet/OIDCFilterSessionStore.java
+++ b/integration/servlet-filter/src/main/java/org/keycloak/adapters/servlet/OIDCFilterSessionStore.java
@@ -69,6 +69,7 @@ public class OIDCFilterSessionStore extends FilterSessionStore implements Adapte
protected void cleanSession(HttpSession session) {
session.removeAttribute(KeycloakAccount.class.getName());
+ session.removeAttribute(KeycloakSecurityContext.class.getName());
clearSavedRequest(session);
}
@@ -138,6 +139,7 @@ public class OIDCFilterSessionStore extends FilterSessionStore implements Adapte
SerializableKeycloakAccount sAccount = new SerializableKeycloakAccount(roles, account.getPrincipal(), securityContext);
HttpSession httpSession = request.getSession();
httpSession.setAttribute(KeycloakAccount.class.getName(), sAccount);
+ httpSession.setAttribute(KeycloakSecurityContext.class.getName(), sAccount.getKeycloakSecurityContext());
if (idMapper != null) idMapper.map(account.getKeycloakSecurityContext().getToken().getClientSession(), account.getPrincipal().getName(), httpSession.getId());
//String username = securityContext.getToken().getSubject();
//log.fine("userSessionManagement.login: " + username);
diff --git a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaSessionTokenStore.java b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaSessionTokenStore.java
index 9d147fa..2b886ee 100755
--- a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaSessionTokenStore.java
+++ b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaSessionTokenStore.java
@@ -52,12 +52,22 @@ public class CatalinaSessionTokenStore extends CatalinaAdapterSessionStore imple
// just in case session got serialized
if (session.getDeployment() == null) session.setCurrentRequestInfo(deployment, this);
- if (session.isActive() && !session.getDeployment().isAlwaysRefreshToken()) return;
+ if (session.isActive() && !session.getDeployment().isAlwaysRefreshToken()) {
+ request.setAttribute(KeycloakSecurityContext.class.getName(), session);
+ request.setUserPrincipal(account.getPrincipal());
+ request.setAuthType("KEYCLOAK");
+ return;
+ }
// FYI: A refresh requires same scope, so same roles will be set. Otherwise, refresh will fail and token will
// not be updated
boolean success = session.refreshExpiredToken(false);
- if (success && session.isActive()) return;
+ if (success && session.isActive()) {
+ request.setAttribute(KeycloakSecurityContext.class.getName(), session);
+ request.setUserPrincipal(account.getPrincipal());
+ request.setAuthType("KEYCLOAK");
+ return;
+ }
// Refresh failed, so user is already logged out from keycloak. Cleanup and expire our session
log.fine("Cleanup and expire session " + catalinaSession.getId() + " after failed refresh");
@@ -68,6 +78,7 @@ public class CatalinaSessionTokenStore extends CatalinaAdapterSessionStore imple
}
protected void cleanSession(Session catalinaSession) {
+ catalinaSession.getSession().removeAttribute(KeycloakSecurityContext.class.getName());
catalinaSession.getSession().removeAttribute(OidcKeycloakAccount.class.getName());
catalinaSession.setPrincipal(null);
catalinaSession.setAuthType(null);
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletSessionTokenStore.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletSessionTokenStore.java
index 5996589..ce82584 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletSessionTokenStore.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletSessionTokenStore.java
@@ -68,7 +68,8 @@ public class ServletSessionTokenStore implements AdapterTokenStore {
return true;
} else {
log.debug("Refresh failed. Account was not active. Returning null and invalidating Http session");
- session.setAttribute(KeycloakUndertowAccount.class.getName(), null);
+ session.removeAttribute(KeycloakSecurityContext.class.getName());
+ session.removeAttribute(KeycloakUndertowAccount.class.getName());
session.invalidate();
return false;
}
@@ -79,6 +80,7 @@ public class ServletSessionTokenStore implements AdapterTokenStore {
final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
HttpSession session = getSession(true);
session.setAttribute(KeycloakUndertowAccount.class.getName(), account);
+ session.setAttribute(KeycloakSecurityContext.class.getName(), account.getKeycloakSecurityContext());
sessionManagement.login(servletRequestContext.getDeployment().getSessionManager());
}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowSessionTokenStore.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowSessionTokenStore.java
index f9fa6c0..5015062 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowSessionTokenStore.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowSessionTokenStore.java
@@ -5,6 +5,7 @@ import io.undertow.server.HttpServerExchange;
import io.undertow.server.session.Session;
import io.undertow.util.Sessions;
import org.jboss.logging.Logger;
+import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.AdapterTokenStore;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.OidcKeycloakAccount;
@@ -65,6 +66,7 @@ public class UndertowSessionTokenStore implements AdapterTokenStore {
} else {
log.debug("Account was not active, returning false");
session.removeAttribute(KeycloakUndertowAccount.class.getName());
+ session.removeAttribute(KeycloakSecurityContext.class.getName());
session.invalidate(exchange);
return false;
}
@@ -84,6 +86,7 @@ public class UndertowSessionTokenStore implements AdapterTokenStore {
public void saveAccountInfo(OidcKeycloakAccount account) {
Session session = Sessions.getOrCreateSession(exchange);
session.setAttribute(KeycloakUndertowAccount.class.getName(), account);
+ session.setAttribute(KeycloakSecurityContext.class.getName(), account.getKeycloakSecurityContext());
sessionManagement.login(session.getSessionManager());
}
diff --git a/saml/client-adapter/jetty/jetty-core/src/main/java/org/keycloak/adapters/saml/jetty/AbstractSamlAuthenticator.java b/saml/client-adapter/jetty/jetty-core/src/main/java/org/keycloak/adapters/saml/jetty/AbstractSamlAuthenticator.java
index 2df0fad..991d89b 100755
--- a/saml/client-adapter/jetty/jetty-core/src/main/java/org/keycloak/adapters/saml/jetty/AbstractSamlAuthenticator.java
+++ b/saml/client-adapter/jetty/jetty-core/src/main/java/org/keycloak/adapters/saml/jetty/AbstractSamlAuthenticator.java
@@ -1,6 +1,8 @@
package org.keycloak.adapters.saml.jetty;
import org.eclipse.jetty.security.DefaultUserIdentity;
+import org.eclipse.jetty.security.IdentityService;
+import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.security.authentication.DeferredAuthentication;
@@ -108,12 +110,45 @@ public abstract class AbstractSamlAuthenticator extends LoginAuthenticator {
}
+ private class DummyLoginService implements LoginService {
+ @Override
+ public String getName() {
+ return null;
+ }
+
+ @Override
+ public UserIdentity login(String username, Object credentials) {
+ return null;
+ }
+
+ @Override
+ public boolean validate(UserIdentity user) {
+ return false;
+ }
+
+ @Override
+ public IdentityService getIdentityService() {
+ return null;
+ }
+
+ @Override
+ public void setIdentityService(IdentityService service) {
+
+ }
+
+ @Override
+ public void logout(UserIdentity user) {
+
+ }
+ }
@Override
public void setConfiguration(AuthConfiguration configuration) {
//super.setConfiguration(configuration);
- initializeKeycloak();
+ // need this so that getUserPrincipal does not throw NPE
+ _loginService = new DummyLoginService();
+ initializeKeycloak();
String error = configuration.getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE);
setErrorPage(error);
}
diff --git a/saml/client-adapter/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/saml/AbstractSamlAuthenticatorValve.java b/saml/client-adapter/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/saml/AbstractSamlAuthenticatorValve.java
index 3119ba7..2acea91 100755
--- a/saml/client-adapter/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/saml/AbstractSamlAuthenticatorValve.java
+++ b/saml/client-adapter/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/saml/AbstractSamlAuthenticatorValve.java
@@ -151,6 +151,12 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
public void invoke(Request request, Response response) throws IOException, ServletException {
log.fine("*********************** SAML ************");
try {
+ CatalinaHttpFacade facade = new CatalinaHttpFacade(response, request);
+ SamlDeployment deployment = deploymentContext.resolveDeployment(facade);
+ if (deployment != null) {
+ // sets request UserPrincipal if logged in. we do this so that the UserPrincipal is available on unsecured, unconstrainted URLs
+ getTokenStore(request, facade, deployment).isLoggedIn();
+ }
super.invoke(request, response);
} finally {
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
index f93c4eb..31eb1eb 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
@@ -143,6 +143,12 @@ public class AdapterTestStrategy extends ExternalResource {
String pageSource = driver.getPageSource();
System.out.println(pageSource);
Assert.assertTrue(pageSource.contains("parameter=hello"));
+ // test that user principal and KeycloakSecurityContext available
+ driver.navigate().to(APP_SERVER_BASE_URL + "/input-portal/insecure");
+ System.out.println("insecure: ");
+ System.out.println(driver.getPageSource());
+ Assert.assertTrue(driver.getPageSource().contains("Insecure Page"));
+ if (System.getProperty("insecure.user.principal.unsupported") == null) Assert.assertTrue(driver.getPageSource().contains("UserPrincipal"));
// test logout
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/FilterAdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/FilterAdapterTest.java
index 39c0368..cb5eac7 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/FilterAdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/FilterAdapterTest.java
@@ -105,6 +105,7 @@ public class FilterAdapterTest {
@Test
public void testSavedPostRequest() throws Exception {
+ System.setProperty("insecure.user.principal.unsupported", "true");
testStrategy.testSavedPostRequest();
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/InputServlet.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/InputServlet.java
index d2dc090..4f4c461 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/InputServlet.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/InputServlet.java
@@ -1,5 +1,8 @@
package org.keycloak.testsuite.adapter;
+import org.junit.Assert;
+import org.keycloak.KeycloakSecurityContext;
+
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@@ -19,6 +22,17 @@ public class InputServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String appBase = System.getProperty("app.server.base.url", "http://localhost:8081");
String actionUrl = appBase + "/input-portal/secured/post";
+ if (req.getRequestURI().endsWith("insecure")) {
+ if (System.getProperty("insecure.user.principal.unsupported") == null) Assert.assertNotNull(req.getUserPrincipal());
+ if (System.getProperty("insecure.user.principal.unsupported") == null) Assert.assertNotNull(req.getAttribute(KeycloakSecurityContext.class.getName()));
+ resp.setContentType("text/html");
+ PrintWriter pw = resp.getWriter();
+ pw.printf("<html><head><title>%s</title></head><body>", "Insecure Page");
+ if (req.getUserPrincipal() != null) pw.printf("UserPrincipal: " + req.getUserPrincipal().getName());
+ pw.print("</body></html>");
+ pw.flush();
+ return;
+ }
resp.setContentType("text/html");