1 package com.atlassian.seraph.auth;
2
3 import com.atlassian.seraph.config.ConfigurationException;
4 import com.atlassian.seraph.config.SecurityConfigFactory;
5 import com.atlassian.seraph.config.SecurityConfigImpl;
6 import com.atlassian.seraph.elevatedsecurity.CountingElevatedSecurityGuard;
7 import com.atlassian.seraph.interceptor.Interceptor;
8 import com.atlassian.seraph.interceptor.LogoutInterceptor;
9 import com.atlassian.seraph.service.rememberme.RememberMeService;
10 import com.mockobjects.dynamic.C;
11 import com.mockobjects.dynamic.Mock;
12 import com.opensymphony.user.provider.ejb.util.Base64;
13 import junit.framework.TestCase;
14 import static org.mockito.Mockito.mock;
15 import static org.mockito.Mockito.when;
16
17 import java.security.Principal;
18 import javax.servlet.http.HttpServletRequest;
19 import javax.servlet.http.HttpServletResponse;
20 import javax.servlet.http.HttpSession;
21
22
23
24
25
26
27
28
29 public class TestDefaultAuthenticator extends TestCase
30 {
31 private Mock request;
32 private Mock response;
33 private SecurityConfigImpl config;
34 private StubAuthenticator authenticator;
35 private Mock session;
36 private Principal user;
37 private RememberMeService rememberMeService;
38
39 protected void setUp() throws Exception
40 {
41 super.setUp();
42 request = new Mock(HttpServletRequest.class);
43 response = new Mock(HttpServletResponse.class);
44 session = new Mock(HttpSession.class);
45 SecurityConfigFactory.setSecurityConfig(null);
46 config = (SecurityConfigImpl) SecurityConfigFactory.getInstance("test-seraph-config.xml");
47 authenticator = (StubAuthenticator) config.getAuthenticator();
48 user = new Principal()
49 {
50 public String getName()
51 {
52 return "Test User";
53 }
54 };
55
56 rememberMeService = mock(RememberMeService.class);
57 authenticator.setRememberMeService(rememberMeService);
58
59 authenticator.addUser(user.getName(),user);
60 }
61
62 public void testLogout() throws ConfigurationException, AuthenticatorException
63 {
64
65 final Mock logoutInterceptor = new Mock(LogoutInterceptor.class);
66
67
68 request.expectAndReturn("getSession", session.proxy());
69 request.expectAndReturn("getSession", session.proxy());
70 request.expectAndReturn("getSession", session.proxy());
71
72 mockOutLoginReason(LoginReason.OUT);
73
74 session.expect("setAttribute", C.args(C.eq(DefaultAuthenticator.LOGGED_IN_KEY), C.IS_NULL));
75 session.expect("setAttribute", C.args(C.eq(DefaultAuthenticator.LOGGED_OUT_KEY), C.eq(Boolean.TRUE)));
76
77 logoutInterceptor.expect("beforeLogout", C.ANY_ARGS);
78 logoutInterceptor.expect("afterLogout", C.ANY_ARGS);
79 config.addInterceptor((Interceptor) logoutInterceptor.proxy());
80
81
82 authenticator.logout((HttpServletRequest) request.proxy(), (HttpServletResponse) response.proxy());
83
84
85 request.verify();
86 response.verify();
87 session.verify();
88 logoutInterceptor.verify();
89 }
90
91 public void testGetUserChecksSessionFirst()
92 {
93
94 request.matchAndReturn("getSession", C.ANY_ARGS, session.proxy());
95 session.matchAndReturn("getAttribute", C.args(C.eq(DefaultAuthenticator.LOGGED_OUT_KEY)), null);
96 session.matchAndReturn("getAttribute", C.args(C.eq(DefaultAuthenticator.LOGGED_IN_KEY)), user);
97
98 mockOutLoginReason(LoginReason.OK);
99
100 final Principal result = authenticator.getUser((HttpServletRequest) request.proxy(), (HttpServletResponse) response.proxy());
101 assertEquals(user, result);
102
103 request.verify();
104 response.verify();
105 session.verify();
106 }
107
108 private StubAuthenticator setupRememberMeCookieState(LoginReason loginReason)
109 {
110 request.matchAndReturn("getSession", C.IS_FALSE, null);
111 request.matchAndReturn("getSession", C.NO_ARGS, session.proxy());
112
113 mockOutLoginReason(loginReason);
114
115 session.matchAndReturn("getAttribute", C.args(C.eq(DefaultAuthenticator.LOGGED_OUT_KEY)), null);
116 session.matchAndReturn("getAttribute", C.args(C.eq(DefaultAuthenticator.LOGGED_IN_KEY)), user);
117 return (StubAuthenticator) authenticator;
118 }
119
120 public void testGetUserChecksCookieIfNoSession()
121 {
122 setupRememberMeCookieState(LoginReason.OK);
123
124 final HttpServletRequest httpServletRequest = (HttpServletRequest) request.proxy();
125 final HttpServletResponse httpServletResponse = (HttpServletResponse) response.proxy();
126
127 when(rememberMeService.getRememberMeCookieAuthenticatedUsername(httpServletRequest,httpServletResponse)).thenReturn(user.getName());
128
129 final Principal result = authenticator.getUser(httpServletRequest, httpServletResponse);
130 assertEquals(user, result);
131
132 request.verify();
133 response.verify();
134 session.verify();
135 }
136
137 public void testGetUserChecksCookieIfNoSession_ButFailedAuthorisation()
138 {
139 authenticator.setDesiredLoginAnswer(false);
140 setupRememberMeCookieState(LoginReason.AUTHORISATION_FAILED);
141
142
143 request.expectAndReturn("getQueryString", "p=v");
144 request.expectAndReturn("getHeader", "Authorization", null);
145
146 final HttpServletRequest httpServletRequest = (HttpServletRequest) request.proxy();
147 final HttpServletResponse httpServletResponse = (HttpServletResponse) response.proxy();
148
149 when(rememberMeService.getRememberMeCookieAuthenticatedUsername(httpServletRequest,httpServletResponse)).thenReturn(user.getName());
150
151 final Principal result = authenticator.getUser(httpServletRequest, httpServletResponse);
152 assertNull(result);
153
154 request.verify();
155 response.verify();
156 session.verify();
157 }
158
159
160
161 public void testGetUserReturnsNullWithNoValidAuthentication()
162 {
163 request.matchAndReturn("getSession", C.IS_FALSE, null);
164 request.expectAndReturn("getQueryString", null);
165 request.expectAndReturn("getHeader", C.args(C.eq("Authorization")), null);
166
167 final Principal result = authenticator.getUser((HttpServletRequest) request.proxy(), (HttpServletResponse) response.proxy());
168 assertEquals(null, result);
169
170 request.verify();
171 response.verify();
172 session.verify();
173 }
174
175 public void testGetUserBasicAuthRequiredButMissing()
176 {
177 request.matchAndReturn("getSession", C.IS_FALSE, null);
178 request.matchAndReturn("getCookies", null);
179 request.matchAndReturn("getQueryString", "os_authType=basic");
180
181
182 request.expectAndReturn("getHeader", C.eq("Authorization"), null);
183
184 response.expect("setStatus", C.eq(401));
185 response.expect("setHeader", C.eq("WWW-Authenticate", "BASIC realm=\"protected-area\""));
186
187 final Principal result = authenticator.getUser((HttpServletRequest) request.proxy(), (HttpServletResponse) response.proxy());
188 assertEquals(null, result);
189
190 request.verify();
191 response.verify();
192 session.verify();
193 }
194
195 private StubAuthenticator setupBasicAuthHttpState(LoginReason loginReason)
196 {
197 request.matchAndReturn("getSession", C.IS_FALSE, null);
198 request.matchAndReturn("getCookies", null);
199 request.matchAndReturn("getQueryString", "os_authType=basic");
200
201 mockOutLoginReason(loginReason);
202
203
204 final String token = new String(Base64.encode("username:password".getBytes()));
205 request.expectAndReturn("getHeader", C.eq("Authorization"), "Basic " + token);
206
207 final StubAuthenticator stubAuthenticator = (StubAuthenticator) authenticator;
208 stubAuthenticator.addUser("username", user);
209 return stubAuthenticator;
210 }
211
212 public void testGetUserBasicAuthProvidedUsingRequestParameter()
213 {
214 setupBasicAuthHttpState(LoginReason.OK);
215
216 final Principal result = authenticator.getUser((HttpServletRequest) request.proxy(), (HttpServletResponse) response.proxy());
217 assertEquals(user, result);
218
219 request.verify();
220 response.verify();
221 session.verify();
222 }
223
224 public void testGetUserBasicAuthProvidedUsingRequestParameter_ButFailsElevatedSecurity() throws ConfigurationException
225 {
226 final StubAuthenticator stubAuthenticator = setupBasicAuthHttpState(LoginReason.AUTHENTICATION_DENIED);
227
228 final CountingElevatedSecurityGuard securityGuard = new CountingElevatedSecurityGuard(false,"username");
229 stubAuthenticator.setElevatedSecurityGuard(securityGuard);
230
231
232 response.expect("sendError", C.args(C.eq(401), C.eq("Basic Authentication Failure - Reason : " + LoginReason.AUTHENTICATION_DENIED)));
233
234 final Principal result = authenticator.getUser((HttpServletRequest) request.proxy(), (HttpServletResponse) response.proxy());
235 assertNull(result);
236
237 assertEquals(0, securityGuard.getSuccessCount());
238 assertEquals(1, securityGuard.getFailedCount());
239
240 request.verify();
241 response.verify();
242 session.verify();
243 }
244
245 public void testGetUserBasicAuthProvidedUsingRequestParameter_PassesElevatedSecurity_ButFailsLogin() throws ConfigurationException
246 {
247 final StubAuthenticator stubAuthenticator = setupBasicAuthHttpState(LoginReason.AUTHENTICATED_FAILED);
248 stubAuthenticator.setDesiredLoginAnswer(false);
249
250 final CountingElevatedSecurityGuard securityGuard = new CountingElevatedSecurityGuard(true,"username");
251 stubAuthenticator.setElevatedSecurityGuard(securityGuard);
252
253
254 response.expect("sendError", C.args(C.eq(401), C.eq("Basic Authentication Failure - Reason : " + LoginReason.AUTHENTICATED_FAILED)));
255
256 final Principal result = authenticator.getUser((HttpServletRequest) request.proxy(), (HttpServletResponse) response.proxy());
257 assertNull(result);
258
259 assertEquals(0, securityGuard.getSuccessCount());
260 assertEquals(1, securityGuard.getFailedCount());
261
262 request.verify();
263 response.verify();
264 session.verify();
265 }
266
267 public void testGetUserBasicAuthProvidedUsingRequestParameter_PassesElevatedSecurity_AndPassesLogin() throws ConfigurationException
268 {
269 final StubAuthenticator stubAuthenticator = setupBasicAuthHttpState(LoginReason.OK);
270 stubAuthenticator.setDesiredLoginAnswer(true);
271
272 final CountingElevatedSecurityGuard securityGuard = new CountingElevatedSecurityGuard(true,"username");
273 stubAuthenticator.setElevatedSecurityGuard(securityGuard);
274
275 final Principal result = authenticator.getUser((HttpServletRequest) request.proxy(), (HttpServletResponse) response.proxy());
276 assertEquals(user, result);
277
278 assertEquals(1, securityGuard.getSuccessCount());
279 assertEquals(0, securityGuard.getFailedCount());
280
281 request.verify();
282 response.verify();
283 session.verify();
284 }
285
286 public void testGetUserBasicAuthProvidedUsingHeader()
287 {
288 final String authorizationHeader = "Basic " + new String(Base64.encode("username:password".getBytes()));
289
290 request.matchAndReturn("getSession", C.IS_FALSE, null);
291 request.matchAndReturn("getCookies", null);
292 request.matchAndReturn("getQueryString", null);
293
294 request.expectAndReturn("getHeader", C.eq("Authorization"), authorizationHeader);
295 request.expectAndReturn("getHeader", C.eq("Authorization"), authorizationHeader);
296
297 mockOutLoginReason(LoginReason.OK);
298
299
300 final StubAuthenticator stubAuthenticator = (StubAuthenticator) authenticator;
301 stubAuthenticator.addUser("username", user);
302
303 final CountingElevatedSecurityGuard securityGuard = new CountingElevatedSecurityGuard(true,"username");
304 stubAuthenticator.setElevatedSecurityGuard(securityGuard);
305
306 final Principal result = authenticator.getUser((HttpServletRequest) request.proxy(), (HttpServletResponse) response.proxy());
307 assertEquals(user, result);
308
309 assertEquals(1, securityGuard.getSuccessCount());
310 assertEquals(0, securityGuard.getFailedCount());
311
312 request.verify();
313 response.verify();
314 session.verify();
315 }
316
317 private void mockOutLoginReason(LoginReason loginReason)
318 {
319 request.expectAndReturn("getAttribute", C.args(C.eq("com.atlassian.seraph.auth.LoginReason")), null);
320 request.expect("setAttribute", C.args(C.eq("com.atlassian.seraph.auth.LoginReason"), C.eq(loginReason)));
321
322 response.expect("addHeader", C.ANY_ARGS);
323 }
324 }