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