import org.argeo.api.cms.CmsAuth;
import org.argeo.api.cms.CmsLog;
import org.argeo.cms.auth.RemoteAuthCallbackHandler;
+import org.argeo.cms.auth.RemoteAuthRequest;
+import org.argeo.cms.auth.RemoteAuthResponse;
import org.argeo.cms.auth.RemoteAuthUtils;
import org.argeo.cms.servlet.internal.HttpUtils;
import org.osgi.framework.Bundle;
// use CMS bundle for resources
private Bundle bundle = FrameworkUtil.getBundle(getClass());
+ private final String httpAuthRealm = "Argeo";
+ private final boolean forceBasic = false;
+
public void init(Map<String, String> properties) {
}
public boolean handleSecurity(HttpServletRequest request, HttpServletResponse response) throws IOException {
if (log.isTraceEnabled())
HttpUtils.logRequestHeaders(log, request);
+ RemoteAuthRequest remoteAuthRequest = new ServletHttpRequest(request);
+ RemoteAuthResponse remoteAuthResponse = new ServletHttpResponse(response);
ClassLoader currentThreadContextClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(CmsServletContext.class.getClassLoader());
LoginContext lc;
try {
- lc = CmsAuth.USER.newLoginContext(
- new RemoteAuthCallbackHandler(new ServletHttpRequest(request), new ServletHttpResponse(response)));
+ lc = CmsAuth.USER.newLoginContext(new RemoteAuthCallbackHandler(remoteAuthRequest, remoteAuthResponse));
lc.login();
} catch (LoginException e) {
- lc = processUnauthorized(request, response);
- if (log.isTraceEnabled())
- HttpUtils.logResponseHeaders(log, response);
+ // FIXME better analyse failure so as not to try endlessly
+ if (authIsRequired(remoteAuthRequest, remoteAuthResponse)) {
+ int statusCode = RemoteAuthUtils.askForWwwAuth(remoteAuthResponse, httpAuthRealm, forceBasic);
+ response.setStatus(statusCode);
+ return false;
+
+ } else {
+ lc = RemoteAuthUtils.anonymousLogin(remoteAuthRequest, remoteAuthResponse);
+ }
if (lc == null)
return false;
} finally {
}
Subject subject = lc.getSubject();
- // log.debug("SERVLET CONTEXT: "+subject);
Subject.doAs(subject, new PrivilegedAction<Void>() {
@Override
public Void run() {
// TODO also set login context in order to log out ?
- RemoteAuthUtils.configureRequestSecurity(new ServletHttpRequest(request));
+ RemoteAuthUtils.configureRequestSecurity(remoteAuthRequest);
return null;
}
RemoteAuthUtils.clearRequestSecurity(new ServletHttpRequest(request));
}
- protected LoginContext processUnauthorized(HttpServletRequest request, HttpServletResponse response) {
- // anonymous
- ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
- try {
- Thread.currentThread().setContextClassLoader(CmsServletContext.class.getClassLoader());
- LoginContext lc = CmsAuth.ANONYMOUS.newLoginContext(
- new RemoteAuthCallbackHandler(new ServletHttpRequest(request), new ServletHttpResponse(response)));
- lc.login();
- return lc;
- } catch (LoginException e1) {
- if (log.isDebugEnabled())
- log.error("Cannot log in as anonymous", e1);
- return null;
- } finally {
- Thread.currentThread().setContextClassLoader(currentContextClassLoader);
- }
+ protected boolean authIsRequired(RemoteAuthRequest remoteAuthRequest, RemoteAuthResponse remoteAuthResponse) {
+ return false;
}
+// protected LoginContext processUnauthorized(HttpServletRequest request, HttpServletResponse response) {
+// // anonymous
+// ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
+// try {
+// Thread.currentThread().setContextClassLoader(CmsServletContext.class.getClassLoader());
+// LoginContext lc = CmsAuth.ANONYMOUS.newLoginContext(
+// new RemoteAuthCallbackHandler(new ServletHttpRequest(request), new ServletHttpResponse(response)));
+// lc.login();
+// return lc;
+// } catch (LoginException e1) {
+// if (log.isDebugEnabled())
+// log.error("Cannot log in as anonymous", e1);
+// return null;
+// } finally {
+// Thread.currentThread().setContextClassLoader(currentContextClassLoader);
+// }
+// }
+
@Override
public URL getResource(String name) {
// TODO make it more robust and versatile
package org.argeo.cms.servlet;
-import javax.security.auth.login.LoginContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.argeo.cms.auth.SpnegoLoginModule;
-import org.argeo.util.http.HttpHeader;
+import org.argeo.cms.auth.RemoteAuthRequest;
+import org.argeo.cms.auth.RemoteAuthResponse;
/** Servlet context forcing authentication. */
public class PrivateWwwAuthServletContext extends CmsServletContext {
// TODO make it configurable
- private final String httpAuthRealm = "Argeo";
- private final boolean forceBasic = false;
-
- @Override
- protected LoginContext processUnauthorized(HttpServletRequest request, HttpServletResponse response) {
- askForWwwAuth(request, response);
- return null;
+// private final String httpAuthRealm = "Argeo";
+// private final boolean forceBasic = false;
+
+ protected boolean authIsRequired(RemoteAuthRequest remoteAuthRequest,
+ RemoteAuthResponse remoteAuthResponse) {
+ return true;
}
- protected void askForWwwAuth(HttpServletRequest request, HttpServletResponse response) {
- // response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "basic
- // realm=\"" + httpAuthRealm + "\"");
- if (SpnegoLoginModule.hasAcceptorCredentials() && !forceBasic)// SPNEGO
- response.setHeader(HttpHeader.WWW_AUTHENTICATE.getName(), HttpHeader.NEGOTIATE);
- else
- response.setHeader(HttpHeader.WWW_AUTHENTICATE.getName(),
- HttpHeader.BASIC + " " + HttpHeader.REALM + "=\"" + httpAuthRealm + "\"");
- // 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.setStatus(401);
- }
+// @Override
+// protected LoginContext processUnauthorized(HttpServletRequest request, HttpServletResponse response) {
+// askForWwwAuth(request, response);
+// return null;
+// }
+//
+// protected void askForWwwAuth(HttpServletRequest request, HttpServletResponse response) {
+// // response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "basic
+// // realm=\"" + httpAuthRealm + "\"");
+// if (SpnegoLoginModule.hasAcceptorCredentials() && !forceBasic)// SPNEGO
+// response.setHeader(HttpHeader.WWW_AUTHENTICATE.getName(), HttpHeader.NEGOTIATE);
+// else
+// response.setHeader(HttpHeader.WWW_AUTHENTICATE.getName(),
+// HttpHeader.BASIC + " " + HttpHeader.REALM + "=\"" + httpAuthRealm + "\"");
+//
+// // 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.setStatus(401);
+// }
}
package org.argeo.cms.websocket.server;
-import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.ArrayList;
import java.util.List;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
import javax.websocket.Extension;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import org.argeo.api.cms.CmsAuth;
import org.argeo.api.cms.CmsLog;
-import org.argeo.api.cms.CmsState;
import org.argeo.cms.auth.RemoteAuthCallbackHandler;
+import org.argeo.cms.auth.RemoteAuthRequest;
+import org.argeo.cms.auth.RemoteAuthResponse;
import org.argeo.cms.auth.RemoteAuthSession;
-import org.argeo.cms.servlet.ServletHttpSession;
+import org.argeo.cms.auth.RemoteAuthUtils;
+import org.argeo.cms.servlet.CmsServletContext;
/**
* <strong>Disabled until third party issues are solved.</strong>. Customises
private final static CmsLog log = CmsLog.getLog(CmsWebSocketConfigurator.class);
final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
-
- private CmsState cmsState;
-
- public void start() {
-
- }
-
- public void stop() {
-
- }
@Override
public boolean checkOrigin(String originHeaderValue) {
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
- if (true)
- return;
+// if (true)
+// return;
- RemoteAuthSession httpSession = new ServletHttpSession(
- (javax.servlet.http.HttpSession) request.getHttpSession());
- if (log.isDebugEnabled() && httpSession != null)
- log.debug("Web socket HTTP session id: " + httpSession.getId());
+ WebSocketHandshakeRequest remoteAuthRequest = new WebSocketHandshakeRequest(request);
+ WebSocketHandshakeResponse remoteAuthResponse = new WebSocketHandshakeResponse(response);
+// RemoteAuthSession httpSession = new ServletHttpSession(
+// (javax.servlet.http.HttpSession) request.getHttpSession());
+ RemoteAuthSession remoteAuthSession = remoteAuthRequest.getSession();
+ if (log.isDebugEnabled() && remoteAuthSession != null)
+ log.debug("Web socket HTTP session id: " + remoteAuthSession.getId());
- if (httpSession == null) {
- rejectResponse(response, null);
- }
+// if (remoteAuthSession == null) {
+// rejectResponse(response, null);
+// }
+ ClassLoader currentThreadContextClassLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(CmsServletContext.class.getClassLoader());
+ LoginContext lc;
try {
- LoginContext lc = new LoginContext(CmsAuth.LOGIN_CONTEXT_USER, new RemoteAuthCallbackHandler(httpSession));
+ lc = CmsAuth.USER.newLoginContext(new RemoteAuthCallbackHandler(remoteAuthRequest, remoteAuthResponse));
lc.login();
- if (log.isDebugEnabled())
- log.debug("Web socket logged-in as " + lc.getSubject());
- Subject.doAs(lc.getSubject(), new PrivilegedAction<Void>() {
+ } catch (LoginException e) {
+ // FIXME better analyse failure so as not to try endlessly
+ if (authIsRequired(remoteAuthRequest, remoteAuthResponse)) {
+ int statusCode = RemoteAuthUtils.askForWwwAuth(remoteAuthResponse, "Argeo", true);
+ remoteAuthResponse.setHeader("Status-Code", Integer.toString(statusCode));
+ return;
+ } else {
+ lc = RemoteAuthUtils.anonymousLogin(remoteAuthRequest, remoteAuthResponse);
+ }
+ if (lc == null)
+ rejectResponse(response, e);
+ } finally {
+ Thread.currentThread().setContextClassLoader(currentThreadContextClassLoader);
+ }
- @Override
- public Void run() {
- sec.getUserProperties().put(REMOTE_USER, AccessController.getContext());
- return null;
- }
+ Subject subject = lc.getSubject();
+ Subject.doAs(subject, new PrivilegedAction<Void>() {
- });
- } catch (Exception e) {
- rejectResponse(response, e);
- }
+ @Override
+ public Void run() {
+ // TODO also set login context in order to log out ?
+ RemoteAuthUtils.configureRequestSecurity(remoteAuthRequest);
+ return null;
+ }
+
+ });
+ }
+
+ protected boolean authIsRequired(RemoteAuthRequest remoteAuthRequest, RemoteAuthResponse remoteAuthResponse) {
+ return true;
}
/**
* @param e can be null
*/
protected void rejectResponse(HandshakeResponse response, Exception e) {
+ response.getHeaders().put(HandshakeResponse.SEC_WEBSOCKET_ACCEPT, new ArrayList<String>());
// violent implementation, as suggested in
// https://stackoverflow.com/questions/21763829/jsr-356-how-to-abort-a-websocket-connection-during-the-handshake
// throw new IllegalStateException("Web socket cannot be authenticated");
--- /dev/null
+package org.argeo.cms.websocket.server;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+
+import javax.servlet.http.HttpSession;
+import javax.websocket.server.HandshakeRequest;
+
+import org.argeo.cms.auth.RemoteAuthRequest;
+import org.argeo.cms.auth.RemoteAuthSession;
+import org.argeo.cms.servlet.ServletHttpSession;
+
+public class WebSocketHandshakeRequest implements RemoteAuthRequest {
+ private final HandshakeRequest handshakeRequest;
+ private final HttpSession httpSession;
+
+ private Map<String, Object> attributes = new HashMap<>();
+
+ public WebSocketHandshakeRequest(HandshakeRequest handshakeRequest) {
+ Objects.requireNonNull(handshakeRequest);
+ this.handshakeRequest = handshakeRequest;
+ this.httpSession = (HttpSession) handshakeRequest.getHttpSession();
+// Objects.requireNonNull(this.httpSession);
+ }
+
+ @Override
+ public RemoteAuthSession getSession() {
+ if (httpSession == null)
+ return null;
+ return new ServletHttpSession(httpSession);
+ }
+
+ @Override
+ public RemoteAuthSession createSession() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Locale getLocale() {
+ // TODO check Accept-Language header
+ return Locale.getDefault();
+ }
+
+ @Override
+ public Object getAttribute(String key) {
+ return attributes.get(key);
+ }
+
+ @Override
+ public void setAttribute(String key, Object object) {
+ attributes.put(key, object);
+ }
+
+ @Override
+ public String getHeader(String key) {
+ List<String> values = handshakeRequest.getHeaders().get(key);
+ if (values.size() == 0)
+ return null;
+ if (values.size() > 1)
+ throw new IllegalStateException("More that one value for " + key + ": " + values);
+ return values.get(0);
+ }
+
+ @Override
+ public String getRemoteAddr() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getLocalPort() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getRemotePort() {
+ throw new UnsupportedOperationException();
+ }
+
+}
--- /dev/null
+package org.argeo.cms.websocket.server;
+
+import java.util.Collections;
+
+import javax.websocket.HandshakeResponse;
+
+import org.argeo.cms.auth.RemoteAuthResponse;
+
+public class WebSocketHandshakeResponse implements RemoteAuthResponse {
+ private final HandshakeResponse handshakeResponse;
+
+ public WebSocketHandshakeResponse(HandshakeResponse handshakeResponse) {
+ this.handshakeResponse = handshakeResponse;
+ }
+
+ @Override
+ public void setHeader(String key, String value) {
+ handshakeResponse.getHeaders().put(key, Collections.singletonList(value));
+
+ }
+
+}
RemoteAuthSession getSession();
+ @Deprecated
RemoteAuthSession createSession();
Locale getLocale();
import javax.security.auth.Subject;
import javax.security.auth.kerberos.KerberosTicket;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import org.argeo.api.cms.CmsAuth;
+import org.argeo.api.cms.CmsLog;
import org.argeo.api.cms.CmsSession;
+import org.argeo.cms.internal.http.CmsAuthenticator;
import org.argeo.cms.internal.runtime.CmsContextImpl;
+import org.argeo.util.http.HttpHeader;
import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
/** Remote authentication utilities. */
public class RemoteAuthUtils {
+ private final static CmsLog log = CmsLog.getLog(RemoteAuthUtils.class);
+
static final String REMOTE_USER = "org.osgi.service.http.authentication.remote.user";
private final static Oid KERBEROS_OID;
// private final static Oid KERB_V5_OID, KRB5_PRINCIPAL_NAME_OID;
}
});
}
+
+ public static LoginContext anonymousLogin(RemoteAuthRequest remoteAuthRequest,
+ RemoteAuthResponse remoteAuthResponse) {
+ // anonymous
+ ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(CmsAuthenticator.class.getClassLoader());
+ LoginContext lc = CmsAuth.ANONYMOUS
+ .newLoginContext(new RemoteAuthCallbackHandler(remoteAuthRequest, remoteAuthResponse));
+ lc.login();
+ return lc;
+ } catch (LoginException e1) {
+ if (log.isDebugEnabled())
+ log.error("Cannot log in as anonymous", e1);
+ return null;
+ } finally {
+ Thread.currentThread().setContextClassLoader(currentContextClassLoader);
+ }
+ }
+
+ public static int askForWwwAuth(RemoteAuthResponse remoteAuthResponse, String realm, boolean forceBasic) {
+ // response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "basic
+ // realm=\"" + httpAuthRealm + "\"");
+ if (SpnegoLoginModule.hasAcceptorCredentials() && !forceBasic)// SPNEGO
+ remoteAuthResponse.setHeader(HttpHeader.WWW_AUTHENTICATE.getName(), HttpHeader.NEGOTIATE);
+ else
+ remoteAuthResponse.setHeader(HttpHeader.WWW_AUTHENTICATE.getName(),
+ HttpHeader.BASIC + " " + HttpHeader.REALM + "=\"" + realm + "\"");
+
+ // 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");
+
+ return 401;
+ }
+
}
authorization = (Authorization) request.getAttribute(RemoteAuthRequest.AUTHORIZATION);
if (authorization == null) {// search by session ID
RemoteAuthSession httpSession = request.getSession();
- if (httpSession == null) {
- // TODO make sure this is always safe
- if (log.isTraceEnabled())
- log.trace("Create http session");
- httpSession = request.createSession();
- }
- String httpSessionId = httpSession.getId();
+// if (httpSession == null) {
+// // TODO make sure this is always safe
+// if (log.isTraceEnabled())
+// log.trace("Create http session");
+// httpSession = request.createSession();
+// }
+ if (httpSession != null) {
+ String httpSessionId = httpSession.getId();
// if (log.isTraceEnabled())
// log.trace("HTTP login: " + request.getPathInfo() + " #" + httpSessionId);
- CmsSessionImpl cmsSession = CmsContextImpl.getCmsContext().getCmsSessionByLocalId(httpSessionId);
- if (cmsSession != null && !cmsSession.isAnonymous()) {
- authorization = cmsSession.getAuthorization();
- locale = cmsSession.getLocale();
- if (log.isTraceEnabled())
- log.trace("Retrieved authorization from " + cmsSession);
+ CmsSessionImpl cmsSession = CmsContextImpl.getCmsContext().getCmsSessionByLocalId(httpSessionId);
+ if (cmsSession != null && !cmsSession.isAnonymous()) {
+ authorization = cmsSession.getAuthorization();
+ locale = cmsSession.getLocale();
+ if (log.isTraceEnabled())
+ log.trace("Retrieved authorization from " + cmsSession);
+ }
}
}
sharedState.put(CmsAuthUtils.SHARED_STATE_HTTP_REQUEST, request);
import java.net.MalformedURLException;
import java.net.URL;
import java.net.http.HttpClient;
+import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandler;
import javax.security.auth.login.LoginContext;
import org.argeo.cms.auth.RemoteAuthUtils;
+import org.argeo.util.http.HttpHeader;
public class SpnegoHttpClient {
public static void main(String[] args) throws MalformedURLException {
// String principal = System.getProperty("javax.security.auth.login.name");
- if (args.length == 0 ) {
+ if (args.length == 0) {
System.err.println("usage: java -Djavax.security.auth.login.name=<principal@REALM> "
+ SpnegoHttpClient.class.getName() + " <url>");
System.exit(1);
String url = args[0];
URL u = new URL(url);
String server = u.getHost();
-
+
URL jaasUrl = SpnegoHttpClient.class.getResource("jaas.cfg");
System.setProperty("java.security.auth.login.config", jaasUrl.toExternalForm());
try {
String token = RemoteAuthUtils.getGssToken(lc.getSubject(), "HTTP", server);
HttpRequest request = HttpRequest.newBuilder().uri(u.toURI()) //
- .header("Authorization", "Negotiate " + token) //
+ .header(HttpHeader.AUTHORIZATION.getName(), HttpHeader.NEGOTIATE + " " + token) //
.build();
BodyHandler<String> bodyHandler = BodyHandlers.ofString();
HttpResponse<String> response = httpClient.send(request, bodyHandler);
package org.argeo.cms.client;
import java.net.URI;
+import java.net.URL;
import java.net.http.HttpClient;
import java.net.http.WebSocket;
import java.nio.ByteBuffer;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
+import javax.security.auth.login.LoginContext;
+
+import org.argeo.cms.auth.RemoteAuthUtils;
+import org.argeo.util.http.HttpHeader;
+
/** Tests connectivity to the web socket server. */
public class WebSocketEventClient {
};
+ // SPNEGO
+ URL jaasUrl = SpnegoHttpClient.class.getResource("jaas.cfg");
+ System.setProperty("java.security.auth.login.config", jaasUrl.toExternalForm());
+ LoginContext lc = new LoginContext("SINGLE_USER");
+ lc.login();
+ String token = RemoteAuthUtils.getGssToken(lc.getSubject(), "HTTP", uri.getHost());
+
HttpClient client = HttpClient.newHttpClient();
- CompletableFuture<WebSocket> ws = client.newWebSocketBuilder().buildAsync(uri, listener);
+ CompletableFuture<WebSocket> ws = client.newWebSocketBuilder()
+ .header(HttpHeader.AUTHORIZATION.getName(), HttpHeader.NEGOTIATE + " " + token)
+ .buildAsync(uri, listener);
WebSocket webSocket = ws.get();
webSocket.request(Long.MAX_VALUE);
--- /dev/null
+package org.argeo.cms.internal.http;
+
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.argeo.api.cms.CmsAuth;
+import org.argeo.api.cms.CmsLog;
+import org.argeo.cms.auth.RemoteAuthCallbackHandler;
+import org.argeo.cms.auth.RemoteAuthRequest;
+import org.argeo.cms.auth.RemoteAuthResponse;
+import org.argeo.cms.auth.SpnegoLoginModule;
+import org.argeo.util.http.HttpHeader;
+
+public class AbstractHttpAuthenticator {
+ private final static CmsLog log = CmsLog.getLog(AbstractHttpAuthenticator.class);
+
+
+}
import org.argeo.api.cms.CmsLog;
import org.argeo.cms.auth.CurrentUser;
import org.argeo.cms.auth.RemoteAuthCallbackHandler;
-import org.argeo.cms.auth.SpnegoLoginModule;
-import org.argeo.util.http.HttpHeader;
+import org.argeo.cms.auth.RemoteAuthRequest;
+import org.argeo.cms.auth.RemoteAuthResponse;
+import org.argeo.cms.auth.RemoteAuthUtils;
+import org.argeo.util.CurrentSubject;
import com.sun.net.httpserver.Authenticator;
import com.sun.net.httpserver.HttpExchange;
public Result authenticate(HttpExchange exch) {
// if (log.isTraceEnabled())
// HttpUtils.logRequestHeaders(log, request);
- RemoteAuthHttpExchange remoteAuthHttpExchange = new RemoteAuthHttpExchange(exch);
+ RemoteAuthHttpExchange remoteAuthExchange = new RemoteAuthHttpExchange(exch);
ClassLoader currentThreadContextClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(CmsAuthenticator.class.getClassLoader());
LoginContext lc;
try {
- lc = CmsAuth.USER
- .newLoginContext(new RemoteAuthCallbackHandler(remoteAuthHttpExchange, remoteAuthHttpExchange));
+ lc = CmsAuth.USER.newLoginContext(new RemoteAuthCallbackHandler(remoteAuthExchange, remoteAuthExchange));
lc.login();
} catch (LoginException e) {
// FIXME better analyse failure so as not to try endlessly
- if (authIsRequired(exch)) {
- return askForWwwAuth(exch);
+ if (authIsRequired(remoteAuthExchange,remoteAuthExchange)) {
+ int statusCode = RemoteAuthUtils.askForWwwAuth(remoteAuthExchange, httpAuthRealm, forceBasic);
+ return new Authenticator.Retry(statusCode);
+
} else {
- lc = processUnauthorized(exch);
-// if (log.isTraceEnabled())
-// HttpUtils.logResponseHeaders(log, response);
+ lc = RemoteAuthUtils.anonymousLogin(remoteAuthExchange, remoteAuthExchange);
}
if (lc == null)
return new Authenticator.Failure(403);
Subject subject = lc.getSubject();
+ CurrentSubject.callAs(subject, () -> {
+ RemoteAuthUtils.configureRequestSecurity(remoteAuthExchange);
+ return null;
+ });
// Subject.doAs(subject, new PrivilegedAction<Void>() {
//
// @Override
return new Authenticator.Success(httpPrincipal);
}
- protected boolean authIsRequired(HttpExchange httpExchange) {
+ protected boolean authIsRequired(RemoteAuthRequest remoteAuthRequest,
+ RemoteAuthResponse remoteAuthResponse) {
return true;
}
- protected LoginContext processUnauthorized(HttpExchange httpExchange) {
-
- RemoteAuthHttpExchange remoteAuthExchange = new RemoteAuthHttpExchange(httpExchange);
- // anonymous
- ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
- try {
- Thread.currentThread().setContextClassLoader(CmsAuthenticator.class.getClassLoader());
- LoginContext lc = CmsAuth.ANONYMOUS
- .newLoginContext(new RemoteAuthCallbackHandler(remoteAuthExchange, remoteAuthExchange));
- lc.login();
- return lc;
- } catch (LoginException e1) {
- if (log.isDebugEnabled())
- log.error("Cannot log in as anonymous", e1);
- return null;
- } finally {
- Thread.currentThread().setContextClassLoader(currentContextClassLoader);
- }
- }
-
- protected Authenticator.Retry askForWwwAuth(HttpExchange httpExchange) {
- // response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "basic
- // realm=\"" + httpAuthRealm + "\"");
- if (SpnegoLoginModule.hasAcceptorCredentials() && !forceBasic)// SPNEGO
- httpExchange.getResponseHeaders().set(HttpHeader.WWW_AUTHENTICATE.getName(), HttpHeader.NEGOTIATE);
- else
- httpExchange.getResponseHeaders().set(HttpHeader.WWW_AUTHENTICATE.getName(),
- HttpHeader.BASIC + " " + HttpHeader.REALM + "=\"" + httpAuthRealm + "\"");
-
- // 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");
-
- return new Authenticator.Retry(401);
- }
-
}