]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java
Disable NodeLogger
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / auth / HttpSessionLoginModule.java
1 package org.argeo.cms.auth;
2
3 import java.io.IOException;
4 import java.security.cert.X509Certificate;
5 import java.util.Collection;
6 import java.util.Map;
7 import java.util.StringTokenizer;
8
9 import javax.security.auth.Subject;
10 import javax.security.auth.callback.Callback;
11 import javax.security.auth.callback.CallbackHandler;
12 import javax.security.auth.callback.UnsupportedCallbackException;
13 import javax.security.auth.login.LoginException;
14 import javax.security.auth.spi.LoginModule;
15 import javax.servlet.http.HttpServletRequest;
16 import javax.servlet.http.HttpServletResponse;
17
18 import org.apache.commons.codec.binary.Base64;
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21 import org.argeo.cms.CmsException;
22 import org.osgi.framework.BundleContext;
23 import org.osgi.framework.FrameworkUtil;
24 import org.osgi.framework.InvalidSyntaxException;
25 import org.osgi.framework.ServiceReference;
26 import org.osgi.service.http.HttpContext;
27 import org.osgi.service.useradmin.Authorization;
28
29 public class HttpSessionLoginModule implements LoginModule {
30 private final static Log log = LogFactory.getLog(HttpSessionLoginModule.class);
31
32 private Subject subject = null;
33 private CallbackHandler callbackHandler = null;
34 private Map<String, Object> sharedState = null;
35
36 private HttpServletRequest request = null;
37 private HttpServletResponse response = null;
38
39 private BundleContext bc;
40
41 private Authorization authorization;
42
43 @SuppressWarnings("unchecked")
44 @Override
45 public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
46 Map<String, ?> options) {
47 bc = FrameworkUtil.getBundle(HttpSessionLoginModule.class).getBundleContext();
48 assert bc != null;
49 this.subject = subject;
50 this.callbackHandler = callbackHandler;
51 this.sharedState = (Map<String, Object>) sharedState;
52 }
53
54 @Override
55 public boolean login() throws LoginException {
56 if (callbackHandler == null)
57 return false;
58 HttpRequestCallback httpCallback = new HttpRequestCallback();
59 try {
60 callbackHandler.handle(new Callback[] { httpCallback });
61 } catch (IOException e) {
62 throw new LoginException("Cannot handle http callback: " + e.getMessage());
63 } catch (UnsupportedCallbackException e) {
64 return false;
65 }
66 request = httpCallback.getRequest();
67 if (request == null)
68 return false;
69 authorization = (Authorization) request.getAttribute(HttpContext.AUTHORIZATION);
70 if (authorization == null) {// search by session ID
71 String httpSessionId = request.getSession().getId();
72 // authorization = (Authorization)
73 // request.getSession().getAttribute(HttpContext.AUTHORIZATION);
74 // if (authorization == null) {
75 Collection<ServiceReference<CmsSession>> sr;
76 try {
77 sr = bc.getServiceReferences(CmsSession.class,
78 "(" + CmsSession.SESSION_LOCAL_ID + "=" + httpSessionId + ")");
79 } catch (InvalidSyntaxException e) {
80 throw new CmsException("Cannot get CMS session for id " + httpSessionId, e);
81 }
82 if (sr.size() == 1) {
83 CmsSession cmsSession = bc.getService(sr.iterator().next());
84 authorization = cmsSession.getAuthorization();
85 if (log.isTraceEnabled())
86 log.trace("Retrieved authorization from " + cmsSession);
87 } else if (sr.size() == 0)
88 authorization = null;
89 else
90 throw new CmsException(sr.size() + ">1 web sessions detected for http session " + httpSessionId);
91
92 }
93 sharedState.put(CmsAuthUtils.SHARED_STATE_HTTP_REQUEST, request);
94 extractHttpAuth(request);
95 extractClientCertificate(request);
96 if (authorization == null)
97 return false;
98 sharedState.put(CmsAuthUtils.SHARED_STATE_AUTHORIZATION, authorization);
99 return true;
100 }
101
102 @Override
103 public boolean commit() throws LoginException {
104 if(authorization!=null){
105 CmsAuthUtils.addAuthorization(subject, authorization,request);
106 // CmsAuthUtils.registerSessionAuthorization(bc, request, subject, authorization);
107 }
108
109 // TODO create CmsSession in another module
110 // Authorization authorizationToRegister;
111 // if (authorization == null) {
112 // authorizationToRegister = (Authorization) sharedState.get(CmsAuthUtils.SHARED_STATE_AUTHORIZATION);
113 // }
114 // else { // this login module did the authorization
115 // CmsAuthUtils.addAuthentication(subject, authorization);
116 // authorizationToRegister = authorization;
117 // }
118 // if (authorizationToRegister == null) {
119 // return false;
120 // }
121 // if (request == null)
122 // return false;
123 // CmsAuthUtils.registerSessionAuthorization(bc, request, subject, authorizationToRegister);
124
125 byte[] outToken = (byte[]) sharedState.get(CmsAuthUtils.SHARED_STATE_SPNEGO_OUT_TOKEN);
126 if (outToken != null) {
127 response.setHeader(CmsAuthUtils.HEADER_WWW_AUTHENTICATE,
128 "Negotiate " + java.util.Base64.getEncoder().encodeToString(outToken));
129 }
130
131 if (authorization != null) {
132 // CmsAuthUtils.addAuthentication(subject, authorization);
133 cleanUp();
134 return true;
135 } else {
136 cleanUp();
137 return false;
138 }
139 }
140
141 @Override
142 public boolean abort() throws LoginException {
143 cleanUp();
144 return false;
145 }
146
147 private void cleanUp() {
148 authorization = null;
149 request = null;
150 }
151
152 @Override
153 public boolean logout() throws LoginException {
154 return CmsAuthUtils.logoutSession(bc, subject);
155 }
156
157 private void extractHttpAuth(final HttpServletRequest httpRequest) {
158 String authHeader = httpRequest.getHeader(CmsAuthUtils.HEADER_AUTHORIZATION);
159 if (authHeader != null) {
160 StringTokenizer st = new StringTokenizer(authHeader);
161 if (st.hasMoreTokens()) {
162 String basic = st.nextToken();
163 if (basic.equalsIgnoreCase("Basic")) {
164 try {
165 // TODO manipulate char[]
166 String credentials = new String(Base64.decodeBase64(st.nextToken()), "UTF-8");
167 // log.debug("Credentials: " + credentials);
168 int p = credentials.indexOf(":");
169 if (p != -1) {
170 final String login = credentials.substring(0, p).trim();
171 final char[] password = credentials.substring(p + 1).trim().toCharArray();
172 sharedState.put(CmsAuthUtils.SHARED_STATE_NAME, login);
173 sharedState.put(CmsAuthUtils.SHARED_STATE_PWD, password);
174 } else {
175 throw new CmsException("Invalid authentication token");
176 }
177 } catch (Exception e) {
178 throw new CmsException("Couldn't retrieve authentication", e);
179 }
180 } else if (basic.equalsIgnoreCase("Negotiate")) {
181 String spnegoToken = st.nextToken();
182 byte[] authToken = Base64.decodeBase64(spnegoToken);
183 sharedState.put(CmsAuthUtils.SHARED_STATE_SPNEGO_TOKEN, authToken);
184 }
185 }
186 }
187 }
188
189 private X509Certificate[] extractClientCertificate(HttpServletRequest req) {
190 X509Certificate[] certs = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
191 if (null != certs && certs.length > 0) {
192 return certs;
193 }
194 return null;
195 }
196
197 }