httponly, ie keycloak.js fix
This commit is contained in:
parent
e8f8829a76
commit
b30809d681
6 changed files with 64 additions and 20 deletions
|
@ -89,6 +89,9 @@ var Keycloak = function (config) {
|
||||||
kc.iframe.setAttribute('src', src );
|
kc.iframe.setAttribute('src', src );
|
||||||
kc.iframe.style.display = "none";
|
kc.iframe.style.display = "none";
|
||||||
doc.body.appendChild(kc.iframe);
|
doc.body.appendChild(kc.iframe);
|
||||||
|
if (!kc.iframe.contentWindow.location.origin) {
|
||||||
|
kc.iframe.contentWindow.location.origin = kc.iframe.contentWindow.location.protocol + "//" + kc.iframe.contentWindow.location.host;
|
||||||
|
}
|
||||||
|
|
||||||
var messageCallback = function(event) {
|
var messageCallback = function(event) {
|
||||||
if (event.origin !== kc.iframe.contentWindow.location.origin) {
|
if (event.origin !== kc.iframe.contentWindow.location.origin) {
|
||||||
|
@ -114,6 +117,7 @@ var Keycloak = function (config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
kc.checkLoginIframe = function(success, failure) {
|
kc.checkLoginIframe = function(success, failure) {
|
||||||
|
|
||||||
var msg = {};
|
var msg = {};
|
||||||
if (!success) {
|
if (!success) {
|
||||||
throw "You must define a success method";
|
throw "You must define a success method";
|
||||||
|
@ -125,7 +129,10 @@ var Keycloak = function (config) {
|
||||||
msg.failureId = createCallbackId();
|
msg.failureId = createCallbackId();
|
||||||
kc.callbackMap[msg.successId] = success;
|
kc.callbackMap[msg.successId] = success;
|
||||||
kc.callbackMap[msg.failureId] = failure;
|
kc.callbackMap[msg.failureId] = failure;
|
||||||
kc.iframe.contentWindow.postMessage(msg, kc.iframe.contentWindow.location.origin);
|
var origin = kc.iframe.contentWindow.location.origin;
|
||||||
|
console.log('*** origin: ' + origin);
|
||||||
|
var iframe = kc.iframe;
|
||||||
|
iframe.contentWindow.postMessage(msg, origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
kc.createLoginUrl = function(options) {
|
kc.createLoginUrl = function(options) {
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.keycloak.services.resources.RealmsResource;
|
||||||
import org.keycloak.authentication.AuthProviderStatus;
|
import org.keycloak.authentication.AuthProviderStatus;
|
||||||
import org.keycloak.authentication.AuthUser;
|
import org.keycloak.authentication.AuthUser;
|
||||||
import org.keycloak.authentication.AuthenticationProviderManager;
|
import org.keycloak.authentication.AuthenticationProviderManager;
|
||||||
|
import org.keycloak.services.util.CookieHelper;
|
||||||
import org.keycloak.util.Time;
|
import org.keycloak.util.Time;
|
||||||
|
|
||||||
import javax.ws.rs.core.Cookie;
|
import javax.ws.rs.core.Cookie;
|
||||||
|
@ -89,22 +90,24 @@ public class AuthenticationManager {
|
||||||
maxAge = realm.getCentralLoginLifespan();
|
maxAge = realm.getCentralLoginLifespan();
|
||||||
logger.info("createLoginCookie maxAge: " + maxAge);
|
logger.info("createLoginCookie maxAge: " + maxAge);
|
||||||
}
|
}
|
||||||
builder.cookie(new NewCookie(cookieName, encoded, cookiePath, null, null, maxAge, secureOnly));// todo httponly , true);
|
CookieHelper.addCookie(cookieName, encoded, cookiePath, null, null, maxAge, secureOnly, true);
|
||||||
|
//builder.cookie(new NewCookie(cookieName, encoded, cookiePath, null, null, maxAge, secureOnly));// todo httponly , true);
|
||||||
|
|
||||||
String sessionCookieValue = realm.getName() + "-" + user.getId();
|
String sessionCookieValue = realm.getName() + "-" + user.getId();
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
sessionCookieValue += "-" + session.getId();
|
sessionCookieValue += "-" + session.getId();
|
||||||
}
|
}
|
||||||
builder.cookie(new NewCookie(KEYCLOAK_SESSION_COOKIE, sessionCookieValue, cookiePath, null, null, maxAge, secureOnly));// todo httponly , true);
|
// THIS SHOULD NOT BE A HTTPONLY COOKIE! It is used for OpenID Connect Iframe Session support!
|
||||||
|
builder.cookie(new NewCookie(KEYCLOAK_SESSION_COOKIE, sessionCookieValue, cookiePath, null, null, maxAge, secureOnly));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public NewCookie createRememberMeCookie(RealmModel realm, UriInfo uriInfo) {
|
public void createRememberMeCookie(HttpResponse response, RealmModel realm, UriInfo uriInfo) {
|
||||||
String path = getIdentityCookiePath(realm, uriInfo);
|
String path = getIdentityCookiePath(realm, uriInfo);
|
||||||
boolean secureOnly = !realm.isSslNotRequired();
|
boolean secureOnly = !realm.isSslNotRequired();
|
||||||
// remember me cookie should be persistent
|
// remember me cookie should be persistent
|
||||||
NewCookie cookie = new NewCookie(KEYCLOAK_REMEMBER_ME, "true", path, null, null, realm.getCentralLoginLifespan(), secureOnly);// todo httponly , true);
|
//NewCookie cookie = new NewCookie(KEYCLOAK_REMEMBER_ME, "true", path, null, null, realm.getCentralLoginLifespan(), secureOnly);// todo httponly , true);
|
||||||
return cookie;
|
CookieHelper.addCookie(KEYCLOAK_REMEMBER_ME, "true", path, null, null, realm.getCentralLoginLifespan(), secureOnly, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String encodeToken(RealmModel realm, Object token) {
|
protected String encodeToken(RealmModel realm, Object token) {
|
||||||
|
@ -117,15 +120,14 @@ public class AuthenticationManager {
|
||||||
public void expireIdentityCookie(RealmModel realm, UriInfo uriInfo) {
|
public void expireIdentityCookie(RealmModel realm, UriInfo uriInfo) {
|
||||||
logger.debug("Expiring identity cookie");
|
logger.debug("Expiring identity cookie");
|
||||||
String path = getIdentityCookiePath(realm, uriInfo);
|
String path = getIdentityCookiePath(realm, uriInfo);
|
||||||
String cookieName = KEYCLOAK_IDENTITY_COOKIE;
|
expireCookie(realm, KEYCLOAK_IDENTITY_COOKIE, path, true);
|
||||||
expireCookie(cookieName, path);
|
expireCookie(realm, KEYCLOAK_SESSION_COOKIE, path, false);
|
||||||
expireCookie(KEYCLOAK_SESSION_COOKIE, path);
|
|
||||||
}
|
}
|
||||||
public void expireRememberMeCookie(RealmModel realm, UriInfo uriInfo) {
|
public void expireRememberMeCookie(RealmModel realm, UriInfo uriInfo) {
|
||||||
logger.debug("Expiring remember me cookie");
|
logger.debug("Expiring remember me cookie");
|
||||||
String path = getIdentityCookiePath(realm, uriInfo);
|
String path = getIdentityCookiePath(realm, uriInfo);
|
||||||
String cookieName = KEYCLOAK_REMEMBER_ME;
|
String cookieName = KEYCLOAK_REMEMBER_ME;
|
||||||
expireCookie(cookieName, path);
|
expireCookie(realm, cookieName, path, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getIdentityCookiePath(RealmModel realm, UriInfo uriInfo) {
|
protected String getIdentityCookiePath(RealmModel realm, UriInfo uriInfo) {
|
||||||
|
@ -133,15 +135,10 @@ public class AuthenticationManager {
|
||||||
return uri.getRawPath();
|
return uri.getRawPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void expireCookie(String cookieName, String path) {
|
public void expireCookie(RealmModel realm, String cookieName, String path, boolean httpOnly) {
|
||||||
HttpResponse response = ResteasyProviderFactory.getContextData(HttpResponse.class);
|
|
||||||
if (response == null) {
|
|
||||||
logger.debug("can't expire identity cookie, no HttpResponse");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
logger.debugv("Expiring cookie: {0} path: {1}", cookieName, path);
|
logger.debugv("Expiring cookie: {0} path: {1}", cookieName, path);
|
||||||
NewCookie expireIt = new NewCookie(cookieName, "", path, null, "Expiring cookie", 0, false);
|
boolean secureOnly = !realm.isSslNotRequired();
|
||||||
response.addNewCookie(expireIt);
|
CookieHelper.addCookie(cookieName, "", path, null, "Expiring cookie", 0, secureOnly, httpOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthResult authenticateIdentityCookie(RealmModel realm, UriInfo uriInfo, HttpHeaders headers) {
|
public AuthResult authenticateIdentityCookie(RealmModel realm, UriInfo uriInfo, HttpHeaders headers) {
|
||||||
|
|
|
@ -99,6 +99,7 @@ public class RealmsResource {
|
||||||
@NoCache
|
@NoCache
|
||||||
public String getLoginStatusIframe(final @PathParam("realm") String name,
|
public String getLoginStatusIframe(final @PathParam("realm") String name,
|
||||||
@QueryParam("client_id") String client_id) {
|
@QueryParam("client_id") String client_id) {
|
||||||
|
logger.info("getLoginStatusIframe");
|
||||||
AuthenticationManager auth = new AuthenticationManager(providers);
|
AuthenticationManager auth = new AuthenticationManager(providers);
|
||||||
|
|
||||||
//logger.info("getting login-status-iframe.html for client_id: " + client_id);
|
//logger.info("getting login-status-iframe.html for client_id: " + client_id);
|
||||||
|
|
|
@ -374,8 +374,7 @@ public class TokenService {
|
||||||
AuthenticationStatus status = authManager.authenticateForm(clientConnection, realm, formData);
|
AuthenticationStatus status = authManager.authenticateForm(clientConnection, realm, formData);
|
||||||
|
|
||||||
if (remember) {
|
if (remember) {
|
||||||
NewCookie cookie = authManager.createRememberMeCookie(realm, uriInfo);
|
authManager.createRememberMeCookie(response, realm, uriInfo);
|
||||||
response.addNewCookie(cookie);
|
|
||||||
} else {
|
} else {
|
||||||
authManager.expireRememberMeCookie(realm, uriInfo);
|
authManager.expireRememberMeCookie(realm, uriInfo);
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,6 +258,7 @@ public class AdminConsole {
|
||||||
@Path("js/keycloak.js")
|
@Path("js/keycloak.js")
|
||||||
@Produces("text/javascript")
|
@Produces("text/javascript")
|
||||||
public Response getKeycloakJs() {
|
public Response getKeycloakJs() {
|
||||||
|
logger.info("**** getting console keycloak.js");
|
||||||
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("keycloak.js");
|
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("keycloak.js");
|
||||||
if (inputStream != null) {
|
if (inputStream != null) {
|
||||||
return Response.ok(inputStream).build();
|
return Response.ok(inputStream).build();
|
||||||
|
|
39
services/src/main/java/org/keycloak/services/util/CookieHelper.java
Executable file
39
services/src/main/java/org/keycloak/services/util/CookieHelper.java
Executable file
|
@ -0,0 +1,39 @@
|
||||||
|
package org.keycloak.services.util;
|
||||||
|
|
||||||
|
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||||
|
|
||||||
|
import javax.servlet.http.Cookie;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class CookieHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a response cookie. This solely exists because JAX-RS 1.1 does not support setting HttpOnly cookies
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* @param value
|
||||||
|
* @param path
|
||||||
|
* @param domain
|
||||||
|
* @param comment
|
||||||
|
* @param maxAge
|
||||||
|
* @param secure
|
||||||
|
* @param httpOnly
|
||||||
|
*/
|
||||||
|
public static void addCookie(String name, String value, String path, String domain, String comment, int maxAge, boolean secure, boolean httpOnly) {
|
||||||
|
HttpServletResponse response = ResteasyProviderFactory.getContextData(HttpServletResponse.class);
|
||||||
|
Cookie cookie = new Cookie(name, value);
|
||||||
|
if (path != null) cookie.setPath(path);
|
||||||
|
if (domain != null) cookie.setDomain(domain);
|
||||||
|
if (comment != null) cookie.setComment(comment);
|
||||||
|
cookie.setMaxAge(maxAge);
|
||||||
|
cookie.setSecure(secure);
|
||||||
|
cookie.setHttpOnly(httpOnly);
|
||||||
|
|
||||||
|
response.addCookie(cookie);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue