]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/internal/http/CmsAuthenticator.java
Start supporting JDK HTTP server API
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / internal / http / CmsAuthenticator.java
1 package org.argeo.cms.internal.http;
2
3 import javax.security.auth.Subject;
4 import javax.security.auth.login.LoginContext;
5 import javax.security.auth.login.LoginException;
6
7 import org.argeo.api.cms.CmsAuth;
8 import org.argeo.api.cms.CmsLog;
9 import org.argeo.cms.auth.CurrentUser;
10 import org.argeo.cms.auth.RemoteAuthCallbackHandler;
11 import org.argeo.cms.auth.SpnegoLoginModule;
12
13 import com.sun.net.httpserver.Authenticator;
14 import com.sun.net.httpserver.HttpExchange;
15 import com.sun.net.httpserver.HttpPrincipal;
16
17 public class CmsAuthenticator extends Authenticator {
18 final static String HEADER_AUTHORIZATION = "Authorization";
19 final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
20
21 private final static CmsLog log = CmsLog.getLog(CmsAuthenticator.class);
22
23 // TODO make it configurable
24 private final String httpAuthRealm = "Argeo";
25 private final boolean forceBasic = false;
26
27 @Override
28 public Result authenticate(HttpExchange exch) {
29 // if (log.isTraceEnabled())
30 // HttpUtils.logRequestHeaders(log, request);
31 RemoteAuthHttpExchange remoteAuthHttpExchange = new RemoteAuthHttpExchange(exch);
32 ClassLoader currentThreadContextClassLoader = Thread.currentThread().getContextClassLoader();
33 Thread.currentThread().setContextClassLoader(CmsAuthenticator.class.getClassLoader());
34 LoginContext lc;
35 try {
36 lc = CmsAuth.USER
37 .newLoginContext(new RemoteAuthCallbackHandler(remoteAuthHttpExchange, remoteAuthHttpExchange));
38 lc.login();
39 } catch (LoginException e) {
40 // FIXME better analyse failure so as not to try endlessly
41 if (authIsRequired(exch)) {
42 return askForWwwAuth(exch);
43 } else {
44 lc = processUnauthorized(exch);
45 // if (log.isTraceEnabled())
46 // HttpUtils.logResponseHeaders(log, response);
47 }
48 if (lc == null)
49 return new Authenticator.Failure(403);
50 } finally {
51 Thread.currentThread().setContextClassLoader(currentThreadContextClassLoader);
52 }
53
54 Subject subject = lc.getSubject();
55
56 // Subject.doAs(subject, new PrivilegedAction<Void>() {
57 //
58 // @Override
59 // public Void run() {
60 // // TODO also set login context in order to log out ?
61 // RemoteAuthUtils.configureRequestSecurity(new ServletHttpRequest(request));
62 // return null;
63 // }
64 //
65 // });
66 String username = CurrentUser.getUsername(subject);
67 HttpPrincipal httpPrincipal = new HttpPrincipal(username, httpAuthRealm);
68 return new Authenticator.Success(httpPrincipal);
69 }
70
71 protected boolean authIsRequired(HttpExchange httpExchange) {
72 return false;
73 }
74
75 protected LoginContext processUnauthorized(HttpExchange httpExchange) {
76
77 RemoteAuthHttpExchange remoteAuthExchange = new RemoteAuthHttpExchange(httpExchange);
78 // anonymous
79 ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
80 try {
81 Thread.currentThread().setContextClassLoader(CmsAuthenticator.class.getClassLoader());
82 LoginContext lc = CmsAuth.ANONYMOUS
83 .newLoginContext(new RemoteAuthCallbackHandler(remoteAuthExchange, remoteAuthExchange));
84 lc.login();
85 return lc;
86 } catch (LoginException e1) {
87 if (log.isDebugEnabled())
88 log.error("Cannot log in as anonymous", e1);
89 return null;
90 } finally {
91 Thread.currentThread().setContextClassLoader(currentContextClassLoader);
92 }
93 }
94
95 protected Authenticator.Retry askForWwwAuth(HttpExchange httpExchange) {
96 // response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "basic
97 // realm=\"" + httpAuthRealm + "\"");
98 if (SpnegoLoginModule.hasAcceptorCredentials() && !forceBasic)// SPNEGO
99 httpExchange.getResponseHeaders().set(HEADER_WWW_AUTHENTICATE, "Negotiate");
100 else
101 httpExchange.getResponseHeaders().set(HEADER_WWW_AUTHENTICATE, "Basic realm=\"" + httpAuthRealm + "\"");
102
103 // response.setDateHeader("Date", System.currentTimeMillis());
104 // response.setDateHeader("Expires", System.currentTimeMillis() + (24 *
105 // 60 * 60 * 1000));
106 // response.setHeader("Accept-Ranges", "bytes");
107 // response.setHeader("Connection", "Keep-Alive");
108 // response.setHeader("Keep-Alive", "timeout=5, max=97");
109 // response.setContentType("text/html; charset=UTF-8");
110
111 return new Authenticator.Retry(401);
112 }
113
114 }