From: Mathieu Baudier Date: Sun, 5 Feb 2017 21:46:45 +0000 (+0100) Subject: Improve IPA X-Git-Tag: argeo-commons-2.1.60~18 X-Git-Url: https://git.argeo.org/?p=lgpl%2Fargeo-commons.git;a=commitdiff_plain;h=b8da6ff850049dd39531c1e50f2eef38c4e3298e Improve IPA --- diff --git a/demo/argeo_node_rap.properties b/demo/argeo_node_rap.properties index 3e7ec6651..88ab23abf 100644 --- a/demo/argeo_node_rap.properties +++ b/demo/argeo_node_rap.properties @@ -72,4 +72,5 @@ log4j.configuration=file:../../log4j.properties # DON'T CHANGE BELOW org.eclipse.rap.workbenchAutostart=false -org.eclipse.equinox.http.jetty.autostart=false \ No newline at end of file +org.eclipse.equinox.http.jetty.autostart=false +javax.security.auth.useSubjectCredsOnly=false diff --git a/demo/init/node/.gitignore b/demo/init/node/.gitignore new file mode 100644 index 000000000..288267a14 --- /dev/null +++ b/demo/init/node/.gitignore @@ -0,0 +1 @@ +/krb5.keytab diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsEntryPoint.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsEntryPoint.java index f310f31e2..22a2ba3e1 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsEntryPoint.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsEntryPoint.java @@ -72,7 +72,7 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement // Initial login try { loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, - new HttpRequestCallbackHandler(UiContext.getHttpRequest())); + new HttpRequestCallbackHandler(UiContext.getHttpRequest(), UiContext.getHttpResponse())); loginContext.login(); } catch (LoginException e) { try { diff --git a/org.argeo.cms.ui/src/org/argeo/cms/widgets/auth/CmsLogin.java b/org.argeo.cms.ui/src/org/argeo/cms/widgets/auth/CmsLogin.java index 180999807..54f0ac395 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/widgets/auth/CmsLogin.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/widgets/auth/CmsLogin.java @@ -284,8 +284,10 @@ public class CmsLogin implements CmsStyles, CallbackHandler { ((NameCallback) callback).setName(usernameT.getText()); else if (callback instanceof PasswordCallback && passwordT != null) ((PasswordCallback) callback).setPassword(passwordT.getTextChars()); - else if (callback instanceof HttpRequestCallback) + else if (callback instanceof HttpRequestCallback){ ((HttpRequestCallback) callback).setRequest(UiContext.getHttpRequest()); + ((HttpRequestCallback) callback).setResponse(UiContext.getHttpResponse()); + } else if (callback instanceof LanguageCallback && localeChoice != null) ((LanguageCallback) callback).setLocale(localeChoice.getSelectedLocale()); } diff --git a/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java b/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java index 1562d5cd0..2432d9c0a 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java @@ -32,18 +32,19 @@ class CmsAuthUtils { private final static Log log = LogFactory.getLog(CmsAuthUtils.class); /** Shared HTTP request */ - static final String SHARED_STATE_HTTP_REQUEST = "org.argeo.cms.auth.http.request"; + final static String SHARED_STATE_HTTP_REQUEST = "org.argeo.cms.auth.http.request"; /** From org.osgi.service.http.HttpContext */ - static final String SHARED_STATE_AUTHORIZATION = "org.osgi.service.useradmin.authorization"; + final static String SHARED_STATE_AUTHORIZATION = "org.osgi.service.useradmin.authorization"; /** From com.sun.security.auth.module.*LoginModule */ - static final String SHARED_STATE_NAME = "javax.security.auth.login.name"; + final static String SHARED_STATE_NAME = "javax.security.auth.login.name"; /** From com.sun.security.auth.module.*LoginModule */ - static final String SHARED_STATE_PWD = "javax.security.auth.login.password"; + final static String SHARED_STATE_PWD = "javax.security.auth.login.password"; - static final String SHARED_STATE_SPNEGO_TOKEN = "org.argeo.cms.auth.spnegoToken"; - static final String SHARED_STATE_SPNEGO_OUT_TOKEN = "org.argeo.cms.auth.spnegoOutToken"; + final static String SHARED_STATE_SPNEGO_TOKEN = "org.argeo.cms.auth.spnegoToken"; + final static String SHARED_STATE_SPNEGO_OUT_TOKEN = "org.argeo.cms.auth.spnegoOutToken"; - static final String HEADER_AUTHORIZATION = "Authorization"; + final static String HEADER_AUTHORIZATION = "Authorization"; + final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate"; static void addAuthentication(Subject subject, Authorization authorization) { assert subject != null; diff --git a/org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallback.java b/org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallback.java index d87e70474..611b324d5 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallback.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallback.java @@ -2,9 +2,11 @@ package org.argeo.cms.auth; import javax.security.auth.callback.Callback; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; public class HttpRequestCallback implements Callback { private HttpServletRequest request; + private HttpServletResponse response; public HttpServletRequest getRequest() { return request; @@ -13,4 +15,13 @@ public class HttpRequestCallback implements Callback { public void setRequest(HttpServletRequest request) { this.request = request; } + + public HttpServletResponse getResponse() { + return response; + } + + public void setResponse(HttpServletResponse response) { + this.response = response; + } + } diff --git a/org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallbackHandler.java b/org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallbackHandler.java index 0486d7479..191a11452 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallbackHandler.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallbackHandler.java @@ -6,6 +6,7 @@ import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; /** * Callback handler populating {@link HttpRequestCallback}s with the provided @@ -13,17 +14,20 @@ import javax.servlet.http.HttpServletRequest; */ public class HttpRequestCallbackHandler implements CallbackHandler { final private HttpServletRequest request; + final private HttpServletResponse response; - public HttpRequestCallbackHandler(HttpServletRequest request) { + public HttpRequestCallbackHandler(HttpServletRequest request, HttpServletResponse response) { this.request = request; + this.response = response; } @Override - public void handle(Callback[] callbacks) throws IOException, - UnsupportedCallbackException { + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback callback : callbacks) - if (callback instanceof HttpRequestCallback) + if (callback instanceof HttpRequestCallback) { ((HttpRequestCallback) callback).setRequest(request); + ((HttpRequestCallback) callback).setResponse(response); + } } } diff --git a/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java index b450401ff..382d8fe4a 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java @@ -13,6 +13,7 @@ import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; @@ -33,6 +34,7 @@ public class HttpSessionLoginModule implements LoginModule { private Map sharedState = null; private HttpServletRequest request = null; + private HttpServletResponse response = null; private BundleContext bc; @@ -97,41 +99,6 @@ public class HttpSessionLoginModule implements LoginModule { return true; } - // private Authorization checkHttp() { - // Authorization authorization = null; - // if (request != null) { - // authorization = (Authorization) - // request.getAttribute(HttpContext.AUTHORIZATION); - // if (authorization == null) { - // String httpSessionId = request.getSession().getId(); - // authorization = (Authorization) - // request.getSession().getAttribute(HttpContext.AUTHORIZATION); - // if (authorization == null) { - // Collection> sr; - // try { - // sr = bc.getServiceReferences(WebCmsSession.class, - // "(" + WebCmsSession.CMS_SESSION_ID + "=" + httpSessionId + ")"); - // } catch (InvalidSyntaxException e) { - // throw new CmsException("Cannot get CMS session for id " + httpSessionId, - // e); - // } - // if (sr.size() == 1) { - // WebCmsSession cmsSession = bc.getService(sr.iterator().next()); - // authorization = cmsSession.getAuthorization(); - // if (log.isTraceEnabled()) - // log.trace("Retrieved authorization from " + cmsSession); - // } else if (sr.size() == 0) - // return null; - // else - // throw new CmsException( - // sr.size() + ">1 web sessions detected for http session " + - // httpSessionId); - // } - // } - // } - // return authorization; - // } - @Override public boolean commit() throws LoginException { // TODO create CmsSession in another module @@ -149,6 +116,12 @@ public class HttpSessionLoginModule implements LoginModule { return false; CmsAuthUtils.registerSessionAuthorization(bc, request, subject, authorizationToRegister); + byte[] outToken = (byte[]) sharedState.get(CmsAuthUtils.SHARED_STATE_SPNEGO_OUT_TOKEN); + if (outToken != null) { + response.setHeader(CmsAuthUtils.HEADER_WWW_AUTHENTICATE, + "Negotiate " + java.util.Base64.getEncoder().encodeToString(outToken)); + } + if (authorization != null) { // CmsAuthUtils.addAuthentication(subject, authorization); cleanUp(); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java index c9b44aa8e..bd4444668 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java @@ -149,13 +149,13 @@ class DataHttp implements KernelConstants { return NodeConstants.PATH_FILES + "/" + alias; } - private Subject subjectFromRequest(HttpServletRequest request) { + private Subject subjectFromRequest(HttpServletRequest request, HttpServletResponse response) { Authorization authorization = (Authorization) request.getAttribute(HttpContext.AUTHORIZATION); if (authorization == null) throw new CmsException("Not authenticated"); try { LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, - new HttpRequestCallbackHandler(request)); + new HttpRequestCallbackHandler(request, response)); lc.login(); return lc.getSubject(); } catch (LoginException e) { @@ -165,18 +165,18 @@ class DataHttp implements KernelConstants { private void askForWwwAuth(HttpServletRequest request, HttpServletResponse response) { response.setStatus(401); - response.setHeader(HEADER_WWW_AUTHENTICATE, "basic realm=\"" + - httpAuthRealm + "\""); - + response.setHeader(HEADER_WWW_AUTHENTICATE, "basic realm=\"" + httpAuthRealm + "\""); + // SPNEGO -// response.setHeader(HEADER_WWW_AUTHENTICATE, "Negotiate"); -// response.setDateHeader("Date", System.currentTimeMillis()); -// response.setDateHeader("Expires", System.currentTimeMillis() + (24 * 60 * 60 * 1000)); -// response.setHeader("Accept-Ranges", "bytes"); -// response.setHeader("Connection", "Keep-Alive"); -// response.setHeader("Keep-Alive", "timeout=5, max=97"); -// response.setContentType("text/html; charset=UTF-8"); - + // response.setHeader(HEADER_WWW_AUTHENTICATE, "Negotiate"); + // response.setDateHeader("Date", System.currentTimeMillis()); + // response.setDateHeader("Expires", System.currentTimeMillis() + (24 * + // 60 * 60 * 1000)); + // response.setHeader("Accept-Ranges", "bytes"); + // response.setHeader("Connection", "Keep-Alive"); + // response.setHeader("Keep-Alive", "timeout=5, max=97"); + // response.setContentType("text/html; charset=UTF-8"); + } private CallbackHandler extractHttpAuth(final HttpServletRequest httpRequest, HttpServletResponse httpResponse) { @@ -201,8 +201,10 @@ class DataHttp implements KernelConstants { ((NameCallback) cb).setName(login); else if (cb instanceof PasswordCallback) ((PasswordCallback) cb).setPassword(password); - else if (cb instanceof HttpRequestCallback) + else if (cb instanceof HttpRequestCallback) { ((HttpRequestCallback) cb).setRequest(httpRequest); + ((HttpRequestCallback) cb).setResponse(httpResponse); + } } } }; @@ -231,7 +233,7 @@ class DataHttp implements KernelConstants { while (!gContext.isEstablished()) { byte[] outToken = gContext.acceptSecContext(authToken, 0, authToken.length); String outTokenStr = Base64.encodeBase64String(outToken); - httpResponse.setHeader("WWW-Authenticate","Negotiate "+ outTokenStr); + httpResponse.setHeader("WWW-Authenticate", "Negotiate " + outTokenStr); } if (gContext.isEstablished()) { String clientName = gContext.getSrcName().toString(); @@ -241,13 +243,13 @@ class DataHttp implements KernelConstants { log.debug("Client Principal is: " + gContext.getSrcName()); log.debug("Server Principal is: " + gContext.getTargName()); log.debug("Client Default Role: " + role); - + // TODO log in } } } catch (GSSException gsse) { - log.warn(gsse,gsse); + log.warn(gsse, gsse); } } @@ -292,11 +294,12 @@ class DataHttp implements KernelConstants { KernelUtils.logRequestHeaders(log, request); LoginContext lc; try { - lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request)); + lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, + new HttpRequestCallbackHandler(request, response)); lc.login(); // return true; } catch (LoginException e) { - CallbackHandler token = extractHttpAuth(request,response); + CallbackHandler token = extractHttpAuth(request, response); if (token != null) { try { lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, token); @@ -344,11 +347,12 @@ class DataHttp implements KernelConstants { KernelUtils.logRequestHeaders(log, request); LoginContext lc; try { - lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request)); + lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, + new HttpRequestCallbackHandler(request, response)); lc.login(); // return true; } catch (LoginException e) { - CallbackHandler token = extractHttpAuth(request,response); + CallbackHandler token = extractHttpAuth(request, response); if (token != null) { try { lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, token); @@ -404,10 +408,11 @@ class DataHttp implements KernelConstants { KernelUtils.logRequestHeaders(log, request); LoginContext lc; try { - lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request)); + lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, + new HttpRequestCallbackHandler(request, response)); lc.login(); } catch (CredentialNotFoundException e) { - CallbackHandler token = extractHttpAuth(request,response); + CallbackHandler token = extractHttpAuth(request, response); if (token != null) { try { lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, token); @@ -558,7 +563,7 @@ class DataHttp implements KernelConstants { protected void service(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { try { - Subject subject = subjectFromRequest(request); + Subject subject = subjectFromRequest(request, response); Subject.doAs(subject, new PrivilegedExceptionAction() { @Override public Void run() throws Exception { diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg index 38fe3705f..52bf4c375 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg @@ -13,7 +13,8 @@ NODE { com.sun.security.auth.module.Krb5LoginModule optional keyTab="${osgi.instance.area}node/krb5.keytab" useKeyTab=true - storeKey=true; + storeKey=true + debug=true; org.argeo.cms.auth.DataAdminLoginModule requisite; }; diff --git a/org.argeo.eclipse.ui.rap/src/org/argeo/eclipse/ui/specific/UiContext.java b/org.argeo.eclipse.ui.rap/src/org/argeo/eclipse/ui/specific/UiContext.java index ec3b2e96a..dac270026 100644 --- a/org.argeo.eclipse.ui.rap/src/org/argeo/eclipse/ui/specific/UiContext.java +++ b/org.argeo.eclipse.ui.rap/src/org/argeo/eclipse/ui/specific/UiContext.java @@ -3,6 +3,7 @@ package org.argeo.eclipse.ui.specific; import java.util.Locale; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.eclipse.rap.rwt.RWT; import org.eclipse.swt.widgets.Display; @@ -14,6 +15,10 @@ public class UiContext { return RWT.getRequest(); } + public static HttpServletResponse getHttpResponse() { + return RWT.getResponse(); + } + public static Locale getLocale() { if (Display.getCurrent() != null) return RWT.getUISession().getLocale(); @@ -40,8 +45,7 @@ public class UiContext { public static void setData(String key, Object value) { Display display = getDisplay(); if (display == null) - throw new SingleSourcingException( - "Not display available in RAP context"); + throw new SingleSourcingException("Not display available in RAP context"); display.setData(key, value); }