001: /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
002: *
003: * Licensed under the Apache License, Version 2.0 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at
006: *
007: * http://www.apache.org/licenses/LICENSE-2.0
008: *
009: * Unless required by applicable law or agreed to in writing, software
010: * distributed under the License is distributed on an "AS IS" BASIS,
011: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: * See the License for the specific language governing permissions and
013: * limitations under the License.
014: */
015:
016: package org.acegisecurity.ui.rememberme;
017:
018: import junit.framework.TestCase;
019:
020: import org.acegisecurity.Authentication;
021: import org.acegisecurity.GrantedAuthority;
022: import org.acegisecurity.GrantedAuthorityImpl;
023:
024: import org.acegisecurity.providers.TestingAuthenticationToken;
025:
026: import org.acegisecurity.userdetails.User;
027: import org.acegisecurity.userdetails.UserDetails;
028: import org.acegisecurity.userdetails.UserDetailsService;
029: import org.acegisecurity.userdetails.UsernameNotFoundException;
030:
031: import org.apache.commons.codec.binary.Base64;
032: import org.apache.commons.codec.digest.DigestUtils;
033:
034: import org.springframework.dao.DataAccessException;
035:
036: import org.springframework.mock.web.MockHttpServletRequest;
037: import org.springframework.mock.web.MockHttpServletResponse;
038:
039: import org.springframework.util.StringUtils;
040:
041: import java.util.Date;
042:
043: import javax.servlet.http.Cookie;
044:
045: /**
046: * Tests {@link org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices}.
047: *
048: * @author Ben Alex
049: * @version $Id: TokenBasedRememberMeServicesTests.java 1909 2007-06-19 04:08:19Z vishalpuri $
050: */
051: public class TokenBasedRememberMeServicesTests extends TestCase {
052: //~ Constructors ===================================================================================================
053:
054: public TokenBasedRememberMeServicesTests() {
055: super ();
056: }
057:
058: public TokenBasedRememberMeServicesTests(String arg0) {
059: super (arg0);
060: }
061:
062: //~ Methods ========================================================================================================
063:
064: private long determineExpiryTimeFromBased64EncodedToken(
065: String validToken) {
066: String cookieAsPlainText = new String(Base64
067: .decodeBase64(validToken.getBytes()));
068: String[] cookieTokens = StringUtils.delimitedListToStringArray(
069: cookieAsPlainText, ":");
070:
071: if (cookieTokens.length == 3) {
072: try {
073: return new Long(cookieTokens[1]).longValue();
074: } catch (NumberFormatException nfe) {
075: }
076: }
077:
078: return -1;
079: }
080:
081: private String generateCorrectCookieContentForToken(
082: long expiryTime, String username, String password,
083: String key) {
084: // format is:
085: // username + ":" + expiryTime + ":" + Md5Hex(username + ":" + expiryTime + ":" + password + ":" + key)
086: String signatureValue = new String(DigestUtils.md5Hex(username
087: + ":" + expiryTime + ":" + password + ":" + key));
088: String tokenValue = username + ":" + expiryTime + ":"
089: + signatureValue;
090: String tokenValueBase64 = new String(Base64
091: .encodeBase64(tokenValue.getBytes()));
092:
093: return tokenValueBase64;
094: }
095:
096: public static void main(String[] args) {
097: junit.textui.TestRunner
098: .run(TokenBasedRememberMeServicesTests.class);
099: }
100:
101: public void testAutoLoginIfDoesNotPresentAnyCookies()
102: throws Exception {
103: TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
104: services.setKey("key");
105: services.setUserDetailsService(new MockAuthenticationDao(null,
106: true));
107: //services.afterPropertiesSet();
108:
109: MockHttpServletRequest request = new MockHttpServletRequest();
110: request.setRequestURI("dc");
111:
112: MockHttpServletResponse response = new MockHttpServletResponse();
113:
114: Authentication result = services.autoLogin(request, response);
115:
116: assertNull(result);
117:
118: Cookie returnedCookie = response
119: .getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY);
120: assertNull(returnedCookie); // shouldn't try to invalidate our cookie
121: }
122:
123: public void testAutoLoginIfDoesNotPresentRequiredCookie()
124: throws Exception {
125: TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
126: services.setKey("key");
127: services.setUserDetailsService(new MockAuthenticationDao(null,
128: true));
129: //services.afterPropertiesSet();
130:
131: Cookie cookie = new Cookie("unrelated_cookie", "foobar");
132: MockHttpServletRequest request = new MockHttpServletRequest();
133: request.setCookies(new Cookie[] { cookie });
134:
135: MockHttpServletResponse response = new MockHttpServletResponse();
136:
137: Authentication result = services.autoLogin(request, response);
138:
139: assertNull(result);
140:
141: Cookie returnedCookie = response
142: .getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY);
143: assertNull(returnedCookie); // shouldn't try to invalidate our cookie
144: }
145:
146: public void testAutoLoginIfExpired() throws Exception {
147: UserDetails user = new User("someone", "password", true, true,
148: true, true,
149: new GrantedAuthority[] { new GrantedAuthorityImpl(
150: "ROLE_ABC") });
151:
152: TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
153: services.setKey("key");
154: services.setUserDetailsService(new MockAuthenticationDao(user,
155: false));
156: // services.afterPropertiesSet();
157:
158: Cookie cookie = new Cookie(
159: TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY,
160: generateCorrectCookieContentForToken(System
161: .currentTimeMillis() - 1000000, "someone",
162: "password", "key"));
163: MockHttpServletRequest request = new MockHttpServletRequest();
164: request.setCookies(new Cookie[] { cookie });
165:
166: MockHttpServletResponse response = new MockHttpServletResponse();
167:
168: Authentication result = services.autoLogin(request, response);
169:
170: assertNull(result);
171:
172: Cookie returnedCookie = response
173: .getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY);
174: assertNotNull(returnedCookie);
175: assertEquals(0, returnedCookie.getMaxAge());
176: }
177:
178: public void testAutoLoginIfMissingThreeTokensInCookieValue()
179: throws Exception {
180: UserDetails user = new User("someone", "password", true, true,
181: true, true,
182: new GrantedAuthority[] { new GrantedAuthorityImpl(
183: "ROLE_ABC") });
184:
185: TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
186: services.setKey("key");
187: services.setUserDetailsService(new MockAuthenticationDao(user,
188: false));
189: //services.afterPropertiesSet();
190:
191: Cookie cookie = new Cookie(
192: TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY,
193: new String(Base64.encodeBase64("x".getBytes())));
194: MockHttpServletRequest request = new MockHttpServletRequest();
195: request.setCookies(new Cookie[] { cookie });
196:
197: MockHttpServletResponse response = new MockHttpServletResponse();
198:
199: Authentication result = services.autoLogin(request, response);
200:
201: assertNull(result);
202:
203: Cookie returnedCookie = response
204: .getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY);
205: assertNotNull(returnedCookie);
206: assertEquals(0, returnedCookie.getMaxAge());
207: }
208:
209: public void testAutoLoginIfNotBase64Encoded() throws Exception {
210: UserDetails user = new User("someone", "password", true, true,
211: true, true,
212: new GrantedAuthority[] { new GrantedAuthorityImpl(
213: "ROLE_ABC") });
214:
215: TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
216: services.setKey("key");
217: services.setUserDetailsService(new MockAuthenticationDao(user,
218: false));
219: //services.afterPropertiesSet();
220:
221: Cookie cookie = new Cookie(
222: TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY,
223: "NOT_BASE_64_ENCODED");
224: MockHttpServletRequest request = new MockHttpServletRequest();
225: request.setCookies(new Cookie[] { cookie });
226:
227: MockHttpServletResponse response = new MockHttpServletResponse();
228:
229: Authentication result = services.autoLogin(request, response);
230:
231: assertNull(result);
232:
233: Cookie returnedCookie = response
234: .getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY);
235: assertNotNull(returnedCookie);
236: assertEquals(0, returnedCookie.getMaxAge());
237: }
238:
239: public void testAutoLoginIfSignatureBlocksDoesNotMatchExpectedValue()
240: throws Exception {
241: UserDetails user = new User("someone", "password", true, true,
242: true, true,
243: new GrantedAuthority[] { new GrantedAuthorityImpl(
244: "ROLE_ABC") });
245:
246: TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
247: services.setKey("key");
248: services.setUserDetailsService(new MockAuthenticationDao(user,
249: false));
250: //services.afterPropertiesSet();
251:
252: Cookie cookie = new Cookie(
253: TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY,
254: generateCorrectCookieContentForToken(System
255: .currentTimeMillis() + 1000000, "someone",
256: "password", "WRONG_KEY"));
257: MockHttpServletRequest request = new MockHttpServletRequest();
258: request.setCookies(new Cookie[] { cookie });
259:
260: MockHttpServletResponse response = new MockHttpServletResponse();
261:
262: Authentication result = services.autoLogin(request, response);
263:
264: assertNull(result);
265:
266: Cookie returnedCookie = response
267: .getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY);
268: assertNotNull(returnedCookie);
269: assertEquals(0, returnedCookie.getMaxAge());
270: }
271:
272: public void testAutoLoginIfTokenDoesNotContainANumberInCookieValue()
273: throws Exception {
274: UserDetails user = new User("someone", "password", true, true,
275: true, true,
276: new GrantedAuthority[] { new GrantedAuthorityImpl(
277: "ROLE_ABC") });
278:
279: TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
280: services.setKey("key");
281: services.setUserDetailsService(new MockAuthenticationDao(user,
282: false));
283: //services.afterPropertiesSet();
284:
285: Cookie cookie = new Cookie(
286: TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY,
287: new String(Base64
288: .encodeBase64("username:NOT_A_NUMBER:signature"
289: .getBytes())));
290: MockHttpServletRequest request = new MockHttpServletRequest();
291: request.setCookies(new Cookie[] { cookie });
292:
293: MockHttpServletResponse response = new MockHttpServletResponse();
294:
295: Authentication result = services.autoLogin(request, response);
296:
297: assertNull(result);
298:
299: Cookie returnedCookie = response
300: .getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY);
301: assertNotNull(returnedCookie);
302: assertEquals(0, returnedCookie.getMaxAge());
303: }
304:
305: public void testAutoLoginIfUserNotFound() throws Exception {
306: TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
307: services.setKey("key");
308: services.setUserDetailsService(new MockAuthenticationDao(null,
309: true));
310: //services.afterPropertiesSet();
311:
312: Cookie cookie = new Cookie(
313: TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY,
314: generateCorrectCookieContentForToken(System
315: .currentTimeMillis() + 1000000, "someone",
316: "password", "key"));
317: MockHttpServletRequest request = new MockHttpServletRequest();
318: request.setCookies(new Cookie[] { cookie });
319:
320: MockHttpServletResponse response = new MockHttpServletResponse();
321:
322: Authentication result = services.autoLogin(request, response);
323:
324: assertNull(result);
325:
326: Cookie returnedCookie = response
327: .getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY);
328: assertNotNull(returnedCookie);
329: assertEquals(0, returnedCookie.getMaxAge());
330: }
331:
332: public void testAutoLoginWithValidToken() throws Exception {
333: UserDetails user = new User("someone", "password", true, true,
334: true, true,
335: new GrantedAuthority[] { new GrantedAuthorityImpl(
336: "ROLE_ABC") });
337:
338: TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
339: services.setKey("key");
340: services.setUserDetailsService(new MockAuthenticationDao(user,
341: false));
342: // services.afterPropertiesSet();
343:
344: Cookie cookie = new Cookie(
345: TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY,
346: generateCorrectCookieContentForToken(System
347: .currentTimeMillis() + 1000000, "someone",
348: "password", "key"));
349: MockHttpServletRequest request = new MockHttpServletRequest();
350: request.setCookies(new Cookie[] { cookie });
351:
352: MockHttpServletResponse response = new MockHttpServletResponse();
353:
354: Authentication result = services.autoLogin(request, response);
355:
356: assertNotNull(result);
357:
358: UserDetails resultingUserDetails = (UserDetails) result
359: .getPrincipal();
360:
361: assertEquals(user, resultingUserDetails);
362: }
363:
364: public void testGettersSetters() {
365: TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
366: services.setUserDetailsService(new MockAuthenticationDao(null,
367: false));
368: assertTrue(services.getUserDetailsService() != null);
369:
370: services.setKey("d");
371: assertEquals("d", services.getKey());
372:
373: assertEquals(TokenBasedRememberMeServices.DEFAULT_PARAMETER,
374: services.getParameter());
375: services.setParameter("some_param");
376: assertEquals("some_param", services.getParameter());
377:
378: services.setTokenValiditySeconds(12);
379: assertEquals(12, services.getTokenValiditySeconds());
380: }
381:
382: public void testLoginFail() {
383: TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
384: MockHttpServletRequest request = new MockHttpServletRequest();
385: request.setRequestURI("fv");
386:
387: MockHttpServletResponse response = new MockHttpServletResponse();
388: services.loginFail(request, response);
389:
390: Cookie cookie = response
391: .getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY);
392: assertNotNull(cookie);
393: assertEquals(0, cookie.getMaxAge());
394: }
395:
396: public void testLoginSuccessIgnoredIfParameterNotSetOrFalse() {
397: TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
398: MockHttpServletRequest request = new MockHttpServletRequest();
399: request.setRequestURI("d");
400: request
401: .addParameter(
402: TokenBasedRememberMeServices.DEFAULT_PARAMETER,
403: "false");
404:
405: MockHttpServletResponse response = new MockHttpServletResponse();
406: services
407: .loginSuccess(
408: request,
409: response,
410: new TestingAuthenticationToken(
411: "someone",
412: "password",
413: new GrantedAuthority[] { new GrantedAuthorityImpl(
414: "ROLE_ABC") }));
415:
416: Cookie cookie = response
417: .getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY);
418: assertNull(cookie);
419: }
420:
421: public void testLoginSuccessNormalWithNonUserDetailsBasedPrincipal() {
422: TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
423: MockHttpServletRequest request = new MockHttpServletRequest();
424: request.setRequestURI("d");
425: request.addParameter(
426: TokenBasedRememberMeServices.DEFAULT_PARAMETER, "true");
427:
428: MockHttpServletResponse response = new MockHttpServletResponse();
429: services
430: .loginSuccess(
431: request,
432: response,
433: new TestingAuthenticationToken(
434: "someone",
435: "password",
436: new GrantedAuthority[] { new GrantedAuthorityImpl(
437: "ROLE_ABC") }));
438:
439: Cookie cookie = response
440: .getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY);
441: assertNotNull(cookie);
442: assertEquals(services.getTokenValiditySeconds(), cookie
443: .getMaxAge());
444: assertTrue(Base64.isArrayByteBase64(cookie.getValue()
445: .getBytes()));
446: assertTrue(new Date().before(new Date(
447: determineExpiryTimeFromBased64EncodedToken(cookie
448: .getValue()))));
449: }
450:
451: public void testLoginSuccessNormalWithUserDetailsBasedPrincipal() {
452: TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
453: MockHttpServletRequest request = new MockHttpServletRequest();
454: request.setRequestURI("d");
455: request.addParameter(
456: TokenBasedRememberMeServices.DEFAULT_PARAMETER, "true");
457:
458: MockHttpServletResponse response = new MockHttpServletResponse();
459: UserDetails user = new User("someone", "password", true, true,
460: true, true,
461: new GrantedAuthority[] { new GrantedAuthorityImpl(
462: "ROLE_ABC") });
463: services
464: .loginSuccess(
465: request,
466: response,
467: new TestingAuthenticationToken(
468: user,
469: "ignored",
470: new GrantedAuthority[] { new GrantedAuthorityImpl(
471: "ROLE_ABC") }));
472:
473: Cookie cookie = response
474: .getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY);
475: assertNotNull(cookie);
476: assertEquals(services.getTokenValiditySeconds(), cookie
477: .getMaxAge());
478: assertTrue(Base64.isArrayByteBase64(cookie.getValue()
479: .getBytes()));
480: assertTrue(new Date().before(new Date(
481: determineExpiryTimeFromBased64EncodedToken(cookie
482: .getValue()))));
483: }
484:
485: //~ Inner Classes ==================================================================================================
486:
487: private class MockAuthenticationDao implements UserDetailsService {
488: private UserDetails toReturn;
489: private boolean throwException;
490:
491: public MockAuthenticationDao(UserDetails toReturn,
492: boolean throwException) {
493: this .toReturn = toReturn;
494: this .throwException = throwException;
495: }
496:
497: public UserDetails loadUserByUsername(String username)
498: throws UsernameNotFoundException, DataAccessException {
499: if (throwException) {
500: throw new UsernameNotFoundException(
501: "as requested by mock");
502: }
503:
504: return toReturn;
505: }
506: }
507: }
|