View Javadoc
1   package org.argeo.cms.integration;
2   
3   import java.io.IOException;
4   import java.util.Locale;
5   import java.util.Set;
6   
7   import javax.security.auth.Subject;
8   import javax.security.auth.callback.Callback;
9   import javax.security.auth.callback.NameCallback;
10  import javax.security.auth.callback.PasswordCallback;
11  import javax.security.auth.callback.UnsupportedCallbackException;
12  import javax.security.auth.login.LoginContext;
13  import javax.security.auth.login.LoginException;
14  import javax.servlet.ServletException;
15  import javax.servlet.http.HttpServlet;
16  import javax.servlet.http.HttpServletRequest;
17  import javax.servlet.http.HttpServletResponse;
18  
19  import org.argeo.api.NodeConstants;
20  import org.argeo.cms.auth.CmsSessionId;
21  import org.argeo.cms.auth.HttpRequestCallback;
22  import org.argeo.cms.auth.HttpRequestCallbackHandler;
23  import org.osgi.service.useradmin.Authorization;
24  
25  import com.fasterxml.jackson.core.JsonGenerator;
26  import com.fasterxml.jackson.databind.ObjectMapper;
27  
28  /** Externally authenticate an http session. */
29  public class CmsLoginServlet extends HttpServlet {
30  	public final static String PARAM_USERNAME = "username";
31  	public final static String PARAM_PASSWORD = "password";
32  
33  	private static final long serialVersionUID = 2478080654328751539L;
34  	private ObjectMapper objectMapper = new ObjectMapper();
35  
36  	@Override
37  	protected void doGet(HttpServletRequest request, HttpServletResponse response)
38  			throws ServletException, IOException {
39  		doPost(request, response);
40  	}
41  
42  	@Override
43  	protected void doPost(HttpServletRequest request, HttpServletResponse response)
44  			throws ServletException, IOException {
45  		LoginContext lc = null;
46  		String username = request.getParameter(PARAM_USERNAME);
47  		String password = request.getParameter(PARAM_PASSWORD);
48  		try {
49  			lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request, response) {
50  				public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
51  					for (Callback callback : callbacks) {
52  						if (callback instanceof NameCallback && username != null)
53  							((NameCallback) callback).setName(username);
54  						else if (callback instanceof PasswordCallback && password != null)
55  							((PasswordCallback) callback).setPassword(password.toCharArray());
56  						else if (callback instanceof HttpRequestCallback) {
57  							((HttpRequestCallback) callback).setRequest(request);
58  							((HttpRequestCallback) callback).setResponse(response);
59  						}
60  					}
61  				}
62  			});
63  			lc.login();
64  
65  			Subject subject = lc.getSubject();
66  			CmsSessionId cmsSessionId = extractFrom(subject.getPrivateCredentials(CmsSessionId.class));
67  			if (cmsSessionId == null) {
68  				response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
69  				return;
70  			}
71  			Authorization authorization = extractFrom(subject.getPrivateCredentials(Authorization.class));
72  			Locale locale = extractFrom(subject.getPublicCredentials(Locale.class));
73  
74  			CmsSessionDescriptor cmsSessionDescriptor = new CmsSessionDescriptor(authorization.getName(),
75  					cmsSessionId.getUuid().toString(), authorization.getRoles(), authorization.toString(),
76  					locale != null ? locale.toString() : null);
77  
78  			response.setContentType("application/json");
79  			JsonGenerator jg = objectMapper.getFactory().createGenerator(response.getWriter());
80  			jg.writeObject(cmsSessionDescriptor);
81  
82  			String redirectTo = redirectTo(request);
83  			if (redirectTo != null)
84  				response.sendRedirect(redirectTo);
85  		} catch (LoginException e) {
86  			response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
87  			return;
88  		}
89  	}
90  
91  	protected <T> T extractFrom(Set<T> creds) {
92  		if (creds.size() > 0)
93  			return creds.iterator().next();
94  		else
95  			return null;
96  	}
97  
98  	/**
99  	 * To be overridden in order to return a richer {@link CmsSessionDescriptor} to
100 	 * be serialized.
101 	 */
102 	protected CmsSessionDescriptor enrichJson(CmsSessionDescriptor cmsSessionDescriptor) {
103 		return cmsSessionDescriptor;
104 	}
105 
106 	protected String redirectTo(HttpServletRequest request) {
107 		return null;
108 	}
109 }