revocation next phase: undertow complete

This commit is contained in:
Bill Burke 2014-03-02 17:32:25 -05:00
parent 7b30cc59b8
commit c8023c6651
14 changed files with 138 additions and 139 deletions

View file

@ -10,17 +10,17 @@ import java.io.Serializable;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeycloakAuthenticatedSession implements Serializable {
public class KeycloakSecurityContext implements Serializable {
protected String tokenString;
protected AccessToken token;
protected IDToken idToken;
protected String idTokenString;
protected transient ResourceMetadata metadata;
public KeycloakAuthenticatedSession() {
public KeycloakSecurityContext() {
}
public KeycloakAuthenticatedSession(String tokenString, AccessToken token, String idTokenString, IDToken idToken, ResourceMetadata metadata) {
public KeycloakSecurityContext(String tokenString, AccessToken token, String idTokenString, IDToken idToken, ResourceMetadata metadata) {
this.tokenString = tokenString;
this.token = token;
this.idToken = idToken;

View file

@ -4,7 +4,7 @@ import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.keycloak.KeycloakAuthenticatedSession;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.HttpClientBuilder;
import org.keycloak.representations.IDToken;
import org.keycloak.util.JsonSerialization;
@ -37,13 +37,13 @@ public class CustomerDatabaseClient {
}
public static IDToken getIDToken(HttpServletRequest req) {
KeycloakAuthenticatedSession session = (KeycloakAuthenticatedSession) req.getAttribute(KeycloakAuthenticatedSession.class.getName());
KeycloakSecurityContext session = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
return session.getIdToken();
}
public static List<String> getCustomers(HttpServletRequest req) throws Failure {
KeycloakAuthenticatedSession session = (KeycloakAuthenticatedSession) req.getAttribute(KeycloakAuthenticatedSession.class.getName());
KeycloakSecurityContext session = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
HttpClient client = new HttpClientBuilder()
.trustStore(session.getMetadata().getTruststore())

View file

@ -4,7 +4,7 @@ import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.keycloak.KeycloakAuthenticatedSession;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.HttpClientBuilder;
import org.keycloak.util.JsonSerialization;
@ -35,7 +35,7 @@ public class ProductDatabaseClient
}
public static List<String> getProducts(HttpServletRequest req) throws Failure {
KeycloakAuthenticatedSession session = (KeycloakAuthenticatedSession)req.getAttribute(KeycloakAuthenticatedSession.class.getName());
KeycloakSecurityContext session = (KeycloakSecurityContext)req.getAttribute(KeycloakSecurityContext.class.getName());
HttpClient client = new HttpClientBuilder()
.trustStore(session.getMetadata().getTruststore())
.hostnameVerification(HttpClientBuilder.HostnameVerificationPolicy.ANY).build();

View file

@ -1,6 +1,6 @@
package org.keycloak.adapters;
import org.keycloak.KeycloakAuthenticatedSession;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.RSATokenVerifier;
import org.keycloak.VerificationException;
import org.keycloak.adapters.config.RealmConfiguration;
@ -15,7 +15,7 @@ import java.io.IOException;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class RefreshableKeycloakSession extends KeycloakAuthenticatedSession {
public class RefreshableKeycloakSession extends KeycloakSecurityContext {
protected static Logger log = Logger.getLogger(RefreshableKeycloakSession.class);

View file

@ -7,7 +7,7 @@ import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
import org.jboss.logging.Logger;
import org.keycloak.KeycloakAuthenticatedSession;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.AdapterConstants;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.adapters.config.AdapterConfig;
@ -45,7 +45,7 @@ public class AuthenticatedActionsValve extends ValveBase {
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
log.debugv("AuthenticatedActionsValve.invoke {0}", request.getRequestURI());
KeycloakAuthenticatedSession session = getSkeletonKeySession(request);
KeycloakSecurityContext session = getSkeletonKeySession(request);
if (corsRequest(request, response, session)) return;
String requestUri = request.getRequestURI();
if (requestUri.endsWith(AdapterConstants.K_QUERY_BEARER_TOKEN)) {
@ -55,17 +55,17 @@ public class AuthenticatedActionsValve extends ValveBase {
getNext().invoke(request, response);
}
public KeycloakAuthenticatedSession getSkeletonKeySession(Request request) {
KeycloakAuthenticatedSession skSession = (KeycloakAuthenticatedSession) request.getAttribute(KeycloakAuthenticatedSession.class.getName());
public KeycloakSecurityContext getSkeletonKeySession(Request request) {
KeycloakSecurityContext skSession = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
if (skSession != null) return skSession;
Session session = request.getSessionInternal();
if (session != null) {
return (KeycloakAuthenticatedSession) session.getNote(KeycloakAuthenticatedSession.class.getName());
return (KeycloakSecurityContext) session.getNote(KeycloakSecurityContext.class.getName());
}
return null;
}
protected void queryBearerToken(Request request, Response response, KeycloakAuthenticatedSession session) throws IOException, ServletException {
protected void queryBearerToken(Request request, Response response, KeycloakSecurityContext session) throws IOException, ServletException {
log.debugv("queryBearerToken {0}", request.getRequestURI());
if (abortTokenResponse(request, response, session)) return;
response.setStatus(HttpServletResponse.SC_OK);
@ -75,7 +75,7 @@ public class AuthenticatedActionsValve extends ValveBase {
}
protected boolean abortTokenResponse(Request request, Response response, KeycloakAuthenticatedSession session) throws IOException {
protected boolean abortTokenResponse(Request request, Response response, KeycloakSecurityContext session) throws IOException {
if (session == null) {
log.debugv("session was null, sending back 401: {0}", request.getRequestURI());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
@ -92,7 +92,7 @@ public class AuthenticatedActionsValve extends ValveBase {
return false;
}
protected boolean corsRequest(Request request, Response response, KeycloakAuthenticatedSession session) throws IOException {
protected boolean corsRequest(Request request, Response response, KeycloakSecurityContext session) throws IOException {
if (!config.isCors()) return false;
log.debugv("CORS enabled + request.getRequestURI()");
String origin = request.getHeader("Origin");

View file

@ -2,7 +2,7 @@ package org.keycloak.adapters.as7;
import org.apache.catalina.connector.Request;
import org.jboss.logging.Logger;
import org.keycloak.KeycloakAuthenticatedSession;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.KeycloakPrincipal;
import org.keycloak.RSATokenVerifier;
import org.keycloak.adapters.ResourceMetadata;
@ -114,8 +114,8 @@ public class CatalinaBearerTokenAuthenticator {
principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), skeletonKeyPrincipal, roles);
request.setUserPrincipal(principal);
request.setAuthType("KEYCLOAK");
KeycloakAuthenticatedSession skSession = new KeycloakAuthenticatedSession(tokenString, token, null, null, resourceMetadata);
request.setAttribute(KeycloakAuthenticatedSession.class.getName(), skSession);
KeycloakSecurityContext skSession = new KeycloakSecurityContext(tokenString, token, null, null, resourceMetadata);
request.setAttribute(KeycloakSecurityContext.class.getName(), skSession);
return true;
}

View file

@ -13,7 +13,7 @@ import org.apache.catalina.core.StandardContext;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.realm.GenericPrincipal;
import org.jboss.logging.Logger;
import org.keycloak.KeycloakAuthenticatedSession;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.KeycloakPrincipal;
import org.keycloak.adapters.AdapterConstants;
import org.keycloak.adapters.RefreshableKeycloakSession;
@ -224,7 +224,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif
*/
protected void checkKeycloakSession(Request request) {
if (request.getSessionInternal(false) == null || request.getSessionInternal().getPrincipal() == null) return;
RefreshableKeycloakSession session = (RefreshableKeycloakSession)request.getSessionInternal().getNote(KeycloakAuthenticatedSession.class.getName());
RefreshableKeycloakSession session = (RefreshableKeycloakSession)request.getSessionInternal().getNote(KeycloakSecurityContext.class.getName());
if (session == null) return;
// just in case session got serialized
session.setRealmConfiguration(realmConfiguration);
@ -236,7 +236,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif
session.refreshExpiredToken();
if (session.isActive()) return;
request.getSessionInternal().removeNote(KeycloakAuthenticatedSession.class.getName());
request.getSessionInternal().removeNote(KeycloakSecurityContext.class.getName());
request.setUserPrincipal(null);
request.setAuthType(null);
request.getSessionInternal().setPrincipal(null);
@ -252,9 +252,9 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif
request.setAuthType("KEYCLOAK");
Session session = request.getSessionInternal();
if (session != null) {
KeycloakAuthenticatedSession skSession = (KeycloakAuthenticatedSession) session.getNote(KeycloakAuthenticatedSession.class.getName());
KeycloakSecurityContext skSession = (KeycloakSecurityContext) session.getNote(KeycloakSecurityContext.class.getName());
if (skSession != null) {
request.setAttribute(KeycloakAuthenticatedSession.class.getName(), skSession);
request.setAttribute(KeycloakSecurityContext.class.getName(), skSession);
}
}
return true;
@ -293,8 +293,8 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif
Session session = request.getSessionInternal(true);
session.setPrincipal(principal);
session.setAuthType("OAUTH");
KeycloakAuthenticatedSession skSession = new RefreshableKeycloakSession(oauth.getTokenString(), oauth.getToken(), oauth.getIdTokenString(), oauth.getIdToken(), resourceMetadata, realmConfiguration, oauth.getRefreshToken());
session.setNote(KeycloakAuthenticatedSession.class.getName(), skSession);
KeycloakSecurityContext skSession = new RefreshableKeycloakSession(oauth.getTokenString(), oauth.getToken(), oauth.getIdTokenString(), oauth.getIdToken(), resourceMetadata, realmConfiguration, oauth.getRefreshToken());
session.setNote(KeycloakSecurityContext.class.getName(), skSession);
String username = token.getSubject();
log.debug("userSessionManage.login: " + username);

View file

@ -2,7 +2,7 @@ package org.keycloak.jaxrs;
import org.jboss.resteasy.logging.Logger;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.KeycloakAuthenticatedSession;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.KeycloakPrincipal;
import org.keycloak.RSATokenVerifier;
import org.keycloak.adapters.ResourceMetadata;
@ -67,8 +67,8 @@ public class JaxrsBearerTokenFilter implements ContainerRequestFilter {
try {
AccessToken token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata.getRealmKey(), resourceMetadata.getRealm());
KeycloakAuthenticatedSession skSession = new KeycloakAuthenticatedSession(tokenString, token, null, null, resourceMetadata);
ResteasyProviderFactory.pushContext(KeycloakAuthenticatedSession.class, skSession);
KeycloakSecurityContext skSession = new KeycloakSecurityContext(tokenString, token, null, null, resourceMetadata);
ResteasyProviderFactory.pushContext(KeycloakSecurityContext.class, skSession);
String callerPrincipal = securityContext.getUserPrincipal() != null ? securityContext.getUserPrincipal().getName() : null;
final KeycloakPrincipal principal = new KeycloakPrincipal(token.getSubject(), callerPrincipal);

View file

@ -2,23 +2,16 @@ package org.keycloak.adapters.undertow;
import io.undertow.security.api.AuthenticationMechanism;
import io.undertow.security.api.SecurityContext;
import io.undertow.security.idm.Account;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.AttachmentKey;
import io.undertow.util.Headers;
import org.jboss.logging.Logger;
import org.keycloak.KeycloakAuthenticatedSession;
import org.keycloak.KeycloakPrincipal;
import org.keycloak.adapters.RefreshableKeycloakSession;
import org.keycloak.adapters.config.RealmConfiguration;
import org.keycloak.adapters.ResourceMetadata;
import org.keycloak.representations.AccessToken;
import org.keycloak.adapters.config.RealmConfiguration;
import org.keycloak.representations.adapters.config.AdapterConfig;
import java.security.Principal;
import java.util.Collections;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
@ -27,7 +20,6 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism
protected Logger log = Logger.getLogger(KeycloakAuthenticationMechanism.class);
public static final AttachmentKey<KeycloakChallenge> KEYCLOAK_CHALLENGE_ATTACHMENT_KEY = AttachmentKey.create(KeycloakChallenge.class);
public static final AttachmentKey<KeycloakAuthenticatedSession> SKELETON_KEY_SESSION_ATTACHMENT_KEY = AttachmentKey.create(KeycloakAuthenticatedSession.class);
protected ResourceMetadata resourceMetadata;
protected AdapterConfig adapterConfig;
@ -41,11 +33,6 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism
this.sslRedirectPort = sslRedirectPort;
}
public KeycloakAuthenticationMechanism(AdapterConfig adapterConfig, ResourceMetadata resourceMetadata) {
this.resourceMetadata = resourceMetadata;
this.adapterConfig = adapterConfig;
}
public KeycloakAuthenticationMechanism(AdapterConfig adapterConfig, RealmConfiguration realmConfig) {
this.resourceMetadata = realmConfig.getMetadata();
this.adapterConfig = adapterConfig;
@ -60,28 +47,38 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism
if (outcome == AuthenticationMechanismOutcome.NOT_AUTHENTICATED) {
exchange.putAttachment(KEYCLOAK_CHALLENGE_ATTACHMENT_KEY, bearer.getChallenge());
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
else if (outcome == AuthenticationMechanismOutcome.AUTHENTICATED) {
completeAuthentication(securityContext, bearer);
} else if (outcome == AuthenticationMechanismOutcome.AUTHENTICATED) {
completeAuthentication(exchange, securityContext, bearer);
return AuthenticationMechanismOutcome.AUTHENTICATED;
}
else if (adapterConfig.isBearerOnly()) {
} else if (adapterConfig.isBearerOnly()) {
exchange.putAttachment(KEYCLOAK_CHALLENGE_ATTACHMENT_KEY, bearer.getChallenge());
return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
}
// We cache account ourselves instead of using the Cache session handler of Undertow because
// Undertow will return a 403 from an invalid account when calling IdentityManager.verify(Account) and
// we want to just return NOT_ATTEMPTED so we can be redirected to relogin
KeycloakUndertowAccount account = checkCachedAccount(exchange);
if (account != null) {
log.info("Cached account found");
securityContext.authenticationComplete(account, "KEYCLOAK", false);
propagateKeycloakContext(exchange, account);
return AuthenticationMechanismOutcome.AUTHENTICATED;
}
OAuthAuthenticator oauth = createOAuthAuthenticator(exchange);
outcome = oauth.authenticate();
if (outcome == AuthenticationMechanismOutcome.NOT_AUTHENTICATED) {
exchange.putAttachment(KEYCLOAK_CHALLENGE_ATTACHMENT_KEY, oauth.getChallenge());
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
else if (outcome == AuthenticationMechanismOutcome.NOT_ATTEMPTED) {
} else if (outcome == AuthenticationMechanismOutcome.NOT_ATTEMPTED) {
exchange.putAttachment(KEYCLOAK_CHALLENGE_ATTACHMENT_KEY, oauth.getChallenge());
return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
}
completeAuthentication(exchange, securityContext, oauth);
// redirect to strip out access code and state query parameters
exchange.getResponseHeaders().put(Headers.LOCATION, oauth.getStrippedOauthParametersRequestUri());
exchange.setResponseCode(302);
exchange.endExchange();
@ -90,12 +87,6 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism
return AuthenticationMechanismOutcome.AUTHENTICATED;
}
public static void sendRedirect(final HttpServerExchange exchange, final String location) {
// TODO - String concatenation to construct URLS is extremely error prone - switch to a URI which will better handle this.
String loc = exchange.getRequestScheme() + "://" + exchange.getHostAndPort() + location;
}
protected OAuthAuthenticator createOAuthAuthenticator(HttpServerExchange exchange) {
return new OAuthAuthenticator(exchange, realmConfig, sslRedirectPort);
}
@ -108,7 +99,11 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism
final KeycloakPrincipal principal = new KeycloakPrincipal(oauth.getToken().getSubject(), null);
RefreshableKeycloakSession session = new RefreshableKeycloakSession(oauth.getTokenString(), oauth.getToken(), oauth.getIdTokenString(), oauth.getIdToken(), resourceMetadata, realmConfig, oauth.getRefreshToken());
KeycloakUndertowAccount account = new KeycloakUndertowAccount(principal, session, adapterConfig, resourceMetadata);
securityContext.authenticationComplete(account, "KEYCLOAK", true);
// We cache account ourselves instead of using the Cache session handler of Undertow because
// Undertow will return a 403 from an invalid account when calling IdentityManager.verify(Account) and
// we want to just return NOT_ATTEMPTED so we can be redirected to relogin
securityContext.authenticationComplete(account, "KEYCLOAK", false);
login(exchange, account);
}
@ -116,12 +111,17 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism
// complete
}
protected void propagateKeycloakContext(HttpServerExchange exchange, KeycloakUndertowAccount account) {
// complete
}
protected void completeAuthentication(SecurityContext securityContext, BearerTokenAuthenticator bearer) {
protected void completeAuthentication(HttpServerExchange exchange, SecurityContext securityContext, BearerTokenAuthenticator bearer) {
final KeycloakPrincipal principal = new KeycloakPrincipal(bearer.getToken().getSubject(), bearer.getSurrogate());
RefreshableKeycloakSession session = new RefreshableKeycloakSession(bearer.getTokenString(), bearer.getToken(), null, null, resourceMetadata, realmConfig, null);
KeycloakUndertowAccount account = new KeycloakUndertowAccount(principal, session, adapterConfig, resourceMetadata);
securityContext.authenticationComplete(account, "KEYCLOAK", false);
propagateKeycloakContext(exchange, account);
}
@Override
@ -132,4 +132,10 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism
}
return new ChallengeResult(false);
}
protected KeycloakUndertowAccount checkCachedAccount(HttpServerExchange exchange) {
return null;
}
}

View file

@ -88,10 +88,24 @@ public class KeycloakServletExtension implements ServletExtension {
return theAuth;
}
}); // authentication
deploymentInfo.addInnerHandlerChainWrapper(ServletPropagateSessionHandler.WRAPPER); // propagates SkeletonKeySession
deploymentInfo.addInnerHandlerChainWrapper(actions); // handles authenticated actions and cors.
deploymentInfo.setIdentityManager(new KeycloakIdentityManager(keycloakConfig, realmConfiguration));
deploymentInfo.setIdentityManager(new IdentityManager() {
@Override
public Account verify(Account account) {
return account;
}
@Override
public Account verify(String id, Credential credential) {
throw new IllegalStateException("Should never be called in Keycloak flow");
}
@Override
public Account verify(Credential credential) {
throw new IllegalStateException("Should never be called in Keycloak flow");
}
});
log.info("Setting jsession cookie path to: " + deploymentInfo.getContextPath());
ServletSessionConfig cookieConfig = new ServletSessionConfig();

View file

@ -70,10 +70,19 @@ public class KeycloakUndertowAccount implements Account, Serializable {
session.setRealmConfiguration(realmConfiguration);
session.setMetadata(realmConfiguration.getMetadata());
log.info("realmConfig notBefore: " + realmConfiguration.getNotBefore());
if (session.isActive()) return true;
if (session.isActive()) {
log.info("session is active");
return true;
}
log.info("session is not active try refresh");
session.refreshExpiredToken();
if (!session.isActive()) return false;
if (!session.isActive()) {
log.info("session is not active return with failure");
return false;
}
log.info("refresh succeeded");
setRoles(session.getToken(), config, realmConfiguration.getMetadata());
return true;

View file

@ -1,21 +1,14 @@
package org.keycloak.adapters.undertow;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.session.Session;
import io.undertow.servlet.api.ConfidentialPortManager;
import io.undertow.servlet.handlers.ServletRequestContext;
import io.undertow.servlet.spec.HttpSessionImpl;
import org.keycloak.KeycloakAuthenticatedSession;
import org.keycloak.KeycloakPrincipal;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.config.RealmConfiguration;
import org.keycloak.adapters.ResourceMetadata;
import org.keycloak.representations.adapters.config.AdapterConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.security.AccessController;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -31,22 +24,47 @@ public class ServletKeycloakAuthenticationMechanism extends KeycloakAuthenticati
this.userSessionManagement = userSessionManagement;
}
public ServletKeycloakAuthenticationMechanism(AdapterConfig config, ResourceMetadata metadata, ConfidentialPortManager portManager) {
super(config, metadata);
this.portManager = portManager;
}
@Override
protected OAuthAuthenticator createOAuthAuthenticator(HttpServerExchange exchange) {
return new ServletOAuthAuthenticator(exchange, realmConfig, portManager);
}
@Override
protected KeycloakUndertowAccount checkCachedAccount(HttpServerExchange exchange) {
final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
HttpServletRequest req = (HttpServletRequest) servletRequestContext.getServletRequest();
HttpSession session = req.getSession(false);
if (session == null) {
log.info("session was null, returning null");
return null;
}
KeycloakUndertowAccount account = (KeycloakUndertowAccount)session.getAttribute(KeycloakUndertowAccount.class.getName());
if (account == null) {
log.info("Account was not in session, returning null");
return null;
}
if (account.isActive(realmConfig, adapterConfig)) return account;
log.info("Account was not active, returning null");
session.setAttribute(KeycloakUndertowAccount.class.getName(), null);
return null;
}
@Override
protected void propagateKeycloakContext(HttpServerExchange exchange, KeycloakUndertowAccount account) {
final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
HttpServletRequest req = (HttpServletRequest) servletRequestContext.getServletRequest();
req.setAttribute(KeycloakSecurityContext.class.getName(), account.getSession());
}
@Override
protected void login(HttpServerExchange exchange, KeycloakUndertowAccount account) {
final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
HttpServletRequest req = (HttpServletRequest) servletRequestContext.getServletRequest();
req.setAttribute(KeycloakSecurityContext.class.getName(), account.getSession());
HttpSession session = req.getSession(true);
session.setAttribute(KeycloakUndertowAccount.class.getName(), account);
userSessionManagement.login(servletRequestContext.getDeployment().getSessionManager(), session, account.getPrincipal().getName());
}

View file

@ -1,57 +0,0 @@
package org.keycloak.adapters.undertow;
import io.undertow.server.HandlerWrapper;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.servlet.handlers.ServletRequestContext;
import org.jboss.logging.Logger;
import org.keycloak.KeycloakAuthenticatedSession;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ServletPropagateSessionHandler implements HttpHandler {
private static final Logger log = Logger.getLogger(ServletPropagateSessionHandler.class);
protected HttpHandler next;
protected ServletPropagateSessionHandler(HttpHandler next) {
this.next = next;
}
public static final HandlerWrapper WRAPPER = new HandlerWrapper() {
@Override
public HttpHandler wrap(HttpHandler handler) {
return new ServletPropagateSessionHandler(handler);
}
};
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
log.debug("handleRequest");
KeycloakUndertowAccount account = (KeycloakUndertowAccount)exchange.getSecurityContext().getAuthenticatedAccount();
if (account == null) {
log.debug("Not logged in, nothing to propagate");
next.handleRequest(exchange);
return;
}
final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
HttpServletRequest req = (HttpServletRequest) servletRequestContext.getServletRequest();
req.setAttribute(KeycloakAuthenticatedSession.class.getName(), account.getSession());
HttpSession session = req.getSession(false);
if (session == null) {
next.handleRequest(exchange);
return;
}
log.debug("propagating to HTTP Session");
session.setAttribute(KeycloakAuthenticatedSession.class.getName(), account.getSession());
next.handleRequest(exchange);
}
}

View file

@ -40,6 +40,7 @@ public class AuthenticationManager {
public static final String KEYCLOAK_REMEMBER_ME = "KEYCLOAK_REMEMBER_ME";
public AccessToken createIdentityToken(RealmModel realm, UserModel user) {
logger.info("createIdentityToken");
AccessToken token = new AccessToken();
token.id(KeycloakModelUtils.generateId());
token.issuedNow();
@ -52,6 +53,7 @@ public class AuthenticationManager {
}
public NewCookie createLoginCookie(RealmModel realm, UserModel user, UriInfo uriInfo, boolean rememberMe) {
logger.info("createLoginCookie");
String cookieName = KEYCLOAK_IDENTITY_COOKIE;
String cookiePath = getIdentityCookiePath(realm, uriInfo);
return createLoginCookie(realm, user, null, cookieName, cookiePath, rememberMe);
@ -140,10 +142,17 @@ public class AuthenticationManager {
try {
AccessToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), realm.getName(), checkActive);
logger.info("identity token verified");
if (checkActive && !token.isActive()) {
logger.info("identity cookie expired");
expireIdentityCookie(realm, uriInfo);
return null;
if (checkActive) {
logger.info("Checking if identity token is active");
if (!token.isActive() || token.getIssuedAt() < realm.getNotBefore()) {
logger.info("identity cookie expired");
expireIdentityCookie(realm, uriInfo);
return null;
} else {
logger.info("token.isActive() : " + token.isActive());
logger.info("token.issuedAt: " + token.getIssuedAt());
logger.info("real.notbefore: " + realm.getNotBefore());
}
}
UserModel user = realm.getUserById(token.getSubject());