1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package edu.internet2.middleware.shibboleth.idp.authn.provider;
19
20 import java.io.IOException;
21 import java.security.Principal;
22 import java.util.Set;
23
24 import javax.security.auth.Subject;
25 import javax.security.auth.callback.Callback;
26 import javax.security.auth.callback.CallbackHandler;
27 import javax.security.auth.callback.NameCallback;
28 import javax.security.auth.callback.PasswordCallback;
29 import javax.security.auth.callback.UnsupportedCallbackException;
30 import javax.security.auth.login.LoginException;
31 import javax.servlet.ServletConfig;
32 import javax.servlet.ServletException;
33 import javax.servlet.http.HttpServlet;
34 import javax.servlet.http.HttpServletRequest;
35 import javax.servlet.http.HttpServletResponse;
36
37 import org.opensaml.xml.util.DatatypeHelper;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 import edu.internet2.middleware.shibboleth.idp.authn.AuthenticationEngine;
42 import edu.internet2.middleware.shibboleth.idp.authn.AuthenticationException;
43 import edu.internet2.middleware.shibboleth.idp.authn.LoginHandler;
44 import edu.internet2.middleware.shibboleth.idp.authn.UsernamePrincipal;
45
46
47
48
49
50 public class UsernamePasswordLoginServlet extends HttpServlet {
51
52
53 private static final long serialVersionUID = -572799841125956990L;
54
55
56 private final Logger log = LoggerFactory.getLogger(UsernamePasswordLoginServlet.class);
57
58
59 private String jaasConfigName = "ShibUserPassAuth";
60
61
62 private final String jaasInitParam = "jaasConfigName";
63
64
65 private String loginPage = "login.jsp";
66
67
68 private final String loginPageInitParam = "loginPage";
69
70
71 private final String failureParam = "loginFailed";
72
73
74 private final String usernameAttribute = "j_username";
75
76
77 private final String passwordAttribute = "j_password";
78
79
80 public void init(ServletConfig config) throws ServletException {
81 super.init(config);
82
83 if (getInitParameter(jaasInitParam) != null) {
84 jaasConfigName = getInitParameter(jaasInitParam);
85 }
86
87 if (getInitParameter(loginPageInitParam) != null) {
88 loginPage = getInitParameter(loginPageInitParam);
89 }
90 if (!loginPage.startsWith("/")) {
91 loginPage = "/" + loginPage;
92 }
93 }
94
95
96 protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException,
97 IOException {
98 String username = request.getParameter(usernameAttribute);
99 String password = request.getParameter(passwordAttribute);
100
101 if (username == null || password == null) {
102 redirectToLoginPage(request, response);
103 return;
104 }
105
106 try {
107 authenticateUser(request, username, password);
108 AuthenticationEngine.returnToAuthenticationEngine(request, response);
109 } catch (LoginException e) {
110 request.setAttribute(failureParam, "true");
111 request.setAttribute(LoginHandler.AUTHENTICATION_EXCEPTION_KEY, new AuthenticationException(e));
112 redirectToLoginPage(request, response);
113 }
114 }
115
116
117
118
119
120
121
122 protected void redirectToLoginPage(HttpServletRequest request, HttpServletResponse response) {
123
124 StringBuilder actionUrlBuilder = new StringBuilder();
125 if(!"".equals(request.getContextPath())){
126 actionUrlBuilder.append(request.getContextPath());
127 }
128 actionUrlBuilder.append(request.getServletPath());
129
130 request.setAttribute("actionUrl", actionUrlBuilder.toString());
131
132 try {
133 request.getRequestDispatcher(loginPage).forward(request, response);
134 log.debug("Redirecting to login page {}", loginPage);
135 } catch (IOException ex) {
136 log.error("Unable to redirect to login page.", ex);
137 } catch (ServletException ex) {
138 log.error("Unable to redirect to login page.", ex);
139 }
140 }
141
142
143
144
145
146
147
148
149
150
151
152 protected void authenticateUser(HttpServletRequest request, String username, String password) throws LoginException {
153 try {
154 log.debug("Attempting to authenticate user {}", username);
155
156 SimpleCallbackHandler cbh = new SimpleCallbackHandler(username, password);
157
158 javax.security.auth.login.LoginContext jaasLoginCtx = new javax.security.auth.login.LoginContext(
159 jaasConfigName, cbh);
160
161 jaasLoginCtx.login();
162 log.debug("Successfully authenticated user {}", username);
163
164 Subject loginSubject = jaasLoginCtx.getSubject();
165
166 Set<Principal> principals = loginSubject.getPrincipals();
167 principals.add(new UsernamePrincipal(username));
168
169 Set<Object> publicCredentials = loginSubject.getPublicCredentials();
170
171 Set<Object> privateCredentials = loginSubject.getPrivateCredentials();
172 privateCredentials.add(new UsernamePasswordCredential(username, password));
173
174 Subject userSubject = new Subject(false, principals, publicCredentials, privateCredentials);
175 request.setAttribute(LoginHandler.SUBJECT_KEY, userSubject);
176 } catch (LoginException e) {
177 log.debug("User authentication for " + username + " failed", e);
178 throw e;
179 } catch (Throwable e) {
180 log.debug("User authentication for " + username + " failed", e);
181 throw new LoginException("unknown authentication error");
182 }
183 }
184
185
186
187
188
189
190 protected class SimpleCallbackHandler implements CallbackHandler {
191
192
193 private String uname;
194
195
196 private String pass;
197
198
199
200
201
202
203
204 public SimpleCallbackHandler(String username, String password) {
205 uname = username;
206 pass = password;
207 }
208
209
210
211
212
213
214
215
216
217 public void handle(final Callback[] callbacks) throws UnsupportedCallbackException {
218
219 if (callbacks == null || callbacks.length == 0) {
220 return;
221 }
222
223 for (Callback cb : callbacks) {
224 if (cb instanceof NameCallback) {
225 NameCallback ncb = (NameCallback) cb;
226 ncb.setName(uname);
227 } else if (cb instanceof PasswordCallback) {
228 PasswordCallback pcb = (PasswordCallback) cb;
229 pcb.setPassword(pass.toCharArray());
230 }
231 }
232 }
233 }
234 }