1 package org
.argeo
.cms
.internal
.http
;
3 import javax
.security
.auth
.Subject
;
4 import javax
.security
.auth
.login
.LoginContext
;
5 import javax
.security
.auth
.login
.LoginException
;
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
.RemoteAuthRequest
;
12 import org
.argeo
.cms
.auth
.RemoteAuthResponse
;
13 import org
.argeo
.cms
.auth
.RemoteAuthUtils
;
14 import org
.argeo
.util
.CurrentSubject
;
16 import com
.sun
.net
.httpserver
.Authenticator
;
17 import com
.sun
.net
.httpserver
.HttpExchange
;
18 import com
.sun
.net
.httpserver
.HttpPrincipal
;
20 public class CmsAuthenticator
extends Authenticator
{
21 // final static String HEADER_AUTHORIZATION = "Authorization";
22 // final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
24 private final static CmsLog log
= CmsLog
.getLog(CmsAuthenticator
.class);
26 // TODO make it configurable
27 private final String httpAuthRealm
= "Argeo";
28 private final boolean forceBasic
= false;
31 public Result
authenticate(HttpExchange exch
) {
32 // if (log.isTraceEnabled())
33 // HttpUtils.logRequestHeaders(log, request);
34 RemoteAuthHttpExchange remoteAuthExchange
= new RemoteAuthHttpExchange(exch
);
35 ClassLoader currentThreadContextClassLoader
= Thread
.currentThread().getContextClassLoader();
36 Thread
.currentThread().setContextClassLoader(CmsAuthenticator
.class.getClassLoader());
39 lc
= CmsAuth
.USER
.newLoginContext(new RemoteAuthCallbackHandler(remoteAuthExchange
, remoteAuthExchange
));
41 } catch (LoginException e
) {
42 // FIXME better analyse failure so as not to try endlessly
43 if (authIsRequired(remoteAuthExchange
,remoteAuthExchange
)) {
44 int statusCode
= RemoteAuthUtils
.askForWwwAuth(remoteAuthExchange
, httpAuthRealm
, forceBasic
);
45 return new Authenticator
.Retry(statusCode
);
48 lc
= RemoteAuthUtils
.anonymousLogin(remoteAuthExchange
, remoteAuthExchange
);
51 return new Authenticator
.Failure(403);
53 Thread
.currentThread().setContextClassLoader(currentThreadContextClassLoader
);
56 Subject subject
= lc
.getSubject();
58 CurrentSubject
.callAs(subject
, () -> {
59 RemoteAuthUtils
.configureRequestSecurity(remoteAuthExchange
);
62 // Subject.doAs(subject, new PrivilegedAction<Void>() {
65 // public Void run() {
66 // // TODO also set login context in order to log out ?
67 // RemoteAuthUtils.configureRequestSecurity(new ServletHttpRequest(request));
72 String username
= CurrentUser
.getUsername(subject
);
73 HttpPrincipal httpPrincipal
= new HttpPrincipal(username
, httpAuthRealm
);
74 return new Authenticator
.Success(httpPrincipal
);
77 protected boolean authIsRequired(RemoteAuthRequest remoteAuthRequest
,
78 RemoteAuthResponse remoteAuthResponse
) {