View Javadoc
1   package org.argeo.cms.integration;
2   
3   import java.io.IOException;
4   import java.time.ZonedDateTime;
5   import java.util.Set;
6   import java.util.UUID;
7   
8   import javax.security.auth.Subject;
9   import javax.security.auth.callback.Callback;
10  import javax.security.auth.callback.UnsupportedCallbackException;
11  import javax.security.auth.login.LoginContext;
12  import javax.security.auth.login.LoginException;
13  import javax.servlet.ServletException;
14  import javax.servlet.http.HttpServlet;
15  import javax.servlet.http.HttpServletRequest;
16  import javax.servlet.http.HttpServletResponse;
17  
18  import org.argeo.api.NodeConstants;
19  import org.argeo.cms.CmsUserManager;
20  import org.argeo.cms.auth.HttpRequestCallback;
21  import org.argeo.cms.auth.HttpRequestCallbackHandler;
22  import org.argeo.naming.NamingUtils;
23  import org.osgi.service.useradmin.Authorization;
24  
25  import com.fasterxml.jackson.core.JsonGenerator;
26  import com.fasterxml.jackson.databind.ObjectMapper;
27  
28  /** Provides access to tokens. */
29  public class CmsTokenServlet extends HttpServlet {
30  	private static final long serialVersionUID = 302918711430864140L;
31  
32  	public final static String PARAM_EXPIRY_DATE = "expiryDate";
33  	public final static String PARAM_TOKEN = "token";
34  
35  	private final static int DEFAULT_HOURS = 24;
36  
37  	private CmsUserManager userManager;
38  	private ObjectMapper objectMapper = new ObjectMapper();
39  
40  	@Override
41  	protected void doPost(HttpServletRequest request, HttpServletResponse response)
42  			throws ServletException, IOException {
43  		LoginContext lc = null;
44  		try {
45  			lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request, response) {
46  				public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
47  					for (Callback callback : callbacks) {
48  						if (callback instanceof HttpRequestCallback) {
49  							((HttpRequestCallback) callback).setRequest(request);
50  							((HttpRequestCallback) callback).setResponse(response);
51  						}
52  					}
53  				}
54  			});
55  			lc.login();
56  		} catch (LoginException e) {
57  			// ignore
58  		}
59  
60  		try {
61  			Subject subject = lc.getSubject();
62  			Authorization authorization = extractFrom(subject.getPrivateCredentials(Authorization.class));
63  			String token = UUID.randomUUID().toString();
64  			String expiryDateStr = request.getParameter(PARAM_EXPIRY_DATE);
65  			ZonedDateTime expiryDate;
66  			if (expiryDateStr != null) {
67  				expiryDate = NamingUtils.ldapDateToZonedDateTime(expiryDateStr);
68  			} else {
69  				expiryDate = ZonedDateTime.now().plusHours(DEFAULT_HOURS);
70  				expiryDateStr = NamingUtils.instantToLdapDate(expiryDate);
71  			}
72  			userManager.addAuthToken(authorization.getName(), token, expiryDate);
73  
74  			TokenDescriptor tokenDescriptor = new TokenDescriptor();
75  			tokenDescriptor.setUsername(authorization.getName());
76  			tokenDescriptor.setToken(token);
77  			tokenDescriptor.setExpiryDate(expiryDateStr);
78  //			tokenDescriptor.setRoles(Collections.unmodifiableSortedSet(new TreeSet<>(Arrays.asList(roles))));
79  
80  			response.setContentType("application/json");
81  			JsonGenerator jg = objectMapper.getFactory().createGenerator(response.getWriter());
82  			jg.writeObject(tokenDescriptor);
83  		} catch (Exception e) {
84  			new CmsExceptionsChain(e).writeAsJson(objectMapper, response);
85  		}
86  	}
87  
88  	@Override
89  	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
90  		// temporarily wrap POST for ease of testing
91  		doPost(req, resp);
92  	}
93  
94  	@Override
95  	protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
96  		try {
97  			String token = req.getParameter(PARAM_TOKEN);
98  			userManager.expireAuthToken(token);
99  		} catch (Exception e) {
100 			new CmsExceptionsChain(e).writeAsJson(objectMapper, resp);
101 		}
102 	}
103 
104 	protected <T> T extractFrom(Set<T> creds) {
105 		if (creds.size() > 0)
106 			return creds.iterator().next();
107 		else
108 			return null;
109 	}
110 
111 	public void setUserManager(CmsUserManager userManager) {
112 		this.userManager = userManager;
113 	}
114 }