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