1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.acegisecurity.providers.cas;
17
18 import java.util.HashMap;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Vector;
22
23 import junit.framework.TestCase;
24
25 import org.acegisecurity.Authentication;
26 import org.acegisecurity.AuthenticationException;
27 import org.acegisecurity.BadCredentialsException;
28 import org.acegisecurity.GrantedAuthority;
29 import org.acegisecurity.GrantedAuthorityImpl;
30 import org.acegisecurity.providers.TestingAuthenticationToken;
31 import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
32 import org.acegisecurity.providers.cas.ticketvalidator.AbstractTicketValidator;
33 import org.acegisecurity.ui.cas.CasProcessingFilter;
34 import org.acegisecurity.userdetails.User;
35 import org.acegisecurity.userdetails.UserDetails;
36
37
38 /***
39 * Tests {@link CasAuthenticationProvider}.
40 *
41 * @author Ben Alex
42 * @version $Id: CasAuthenticationProviderTests.java,v 1.8 2005/11/30 01:23:36 benalex Exp $
43 */
44 public class CasAuthenticationProviderTests extends TestCase {
45
46
47 public CasAuthenticationProviderTests() {
48 super();
49 }
50
51 public CasAuthenticationProviderTests(String arg0) {
52 super(arg0);
53 }
54
55
56
57 public final void setUp() throws Exception {
58 super.setUp();
59 }
60
61 public static void main(String[] args) {
62 junit.textui.TestRunner.run(CasAuthenticationProviderTests.class);
63 }
64
65 public void testAuthenticateStateful() throws Exception {
66 CasAuthenticationProvider cap = new CasAuthenticationProvider();
67 cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
68 cap.setCasProxyDecider(new MockProxyDecider(true));
69 cap.setKey("qwerty");
70
71 StatelessTicketCache cache = new MockStatelessTicketCache();
72 cap.setStatelessTicketCache(cache);
73 cap.setTicketValidator(new MockTicketValidator(true));
74 cap.afterPropertiesSet();
75
76 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(CasProcessingFilter.CAS_STATEFUL_IDENTIFIER,
77 "ST-123");
78
79 Authentication result = cap.authenticate(token);
80
81
82 assertTrue(cache.getByTicketId("ST-456") == null);
83
84 if (!(result instanceof CasAuthenticationToken)) {
85 fail("Should have returned a CasAuthenticationToken");
86 }
87
88 CasAuthenticationToken casResult = (CasAuthenticationToken) result;
89 assertEquals("marissa", casResult.getPrincipal());
90 assertEquals("PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt",
91 casResult.getProxyGrantingTicketIou());
92 assertEquals("https://localhost/portal/j_acegi_cas_security_check",
93 casResult.getProxyList().get(0));
94 assertEquals("ST-123", casResult.getCredentials());
95 assertEquals(new GrantedAuthorityImpl("ROLE_A"),
96 casResult.getAuthorities()[0]);
97 assertEquals(new GrantedAuthorityImpl("ROLE_B"),
98 casResult.getAuthorities()[1]);
99 assertEquals(cap.getKey().hashCode(), casResult.getKeyHash());
100
101
102
103 cap.setTicketValidator(new MockTicketValidator(false));
104
105 Authentication laterResult = cap.authenticate(result);
106 assertEquals(result, laterResult);
107 }
108
109 public void testAuthenticateStateless() throws Exception {
110 CasAuthenticationProvider cap = new CasAuthenticationProvider();
111 cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
112 cap.setCasProxyDecider(new MockProxyDecider(true));
113 cap.setKey("qwerty");
114
115 StatelessTicketCache cache = new MockStatelessTicketCache();
116 cap.setStatelessTicketCache(cache);
117 cap.setTicketValidator(new MockTicketValidator(true));
118 cap.afterPropertiesSet();
119
120 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(CasProcessingFilter.CAS_STATELESS_IDENTIFIER,
121 "ST-456");
122
123 Authentication result = cap.authenticate(token);
124
125
126 assertTrue(cache.getByTicketId("ST-456") != null);
127
128 if (!(result instanceof CasAuthenticationToken)) {
129 fail("Should have returned a CasAuthenticationToken");
130 }
131
132 assertEquals("marissa", result.getPrincipal());
133 assertEquals("ST-456", result.getCredentials());
134
135
136
137 cap.setTicketValidator(new MockTicketValidator(false));
138
139
140 Authentication newResult = cap.authenticate(token);
141 assertEquals("marissa", newResult.getPrincipal());
142 assertEquals("ST-456", newResult.getCredentials());
143 }
144
145 public void testDetectsAMissingTicketId() throws Exception {
146 CasAuthenticationProvider cap = new CasAuthenticationProvider();
147 cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
148 cap.setCasProxyDecider(new MockProxyDecider(true));
149 cap.setKey("qwerty");
150
151 StatelessTicketCache cache = new MockStatelessTicketCache();
152 cap.setStatelessTicketCache(cache);
153 cap.setTicketValidator(new MockTicketValidator(true));
154 cap.afterPropertiesSet();
155
156 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(CasProcessingFilter.CAS_STATEFUL_IDENTIFIER,
157 "");
158
159 try {
160 Authentication result = cap.authenticate(token);
161 fail("Should have thrown BadCredentialsException");
162 } catch (BadCredentialsException expected) {
163 assertEquals("Failed to provide a CAS service ticket to validate",
164 expected.getMessage());
165 }
166 }
167
168 public void testDetectsAnInvalidKey() throws Exception {
169 CasAuthenticationProvider cap = new CasAuthenticationProvider();
170 cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
171 cap.setCasProxyDecider(new MockProxyDecider(true));
172 cap.setKey("qwerty");
173
174 StatelessTicketCache cache = new MockStatelessTicketCache();
175 cap.setStatelessTicketCache(cache);
176 cap.setTicketValidator(new MockTicketValidator(true));
177 cap.afterPropertiesSet();
178
179 CasAuthenticationToken token = new CasAuthenticationToken("WRONG_KEY",
180 "test", "credentials",
181 new GrantedAuthority[] {new GrantedAuthorityImpl("XX")},
182 makeUserDetails(), new Vector(), "IOU-xxx");
183
184 try {
185 Authentication result = cap.authenticate(token);
186 fail("Should have thrown BadCredentialsException");
187 } catch (BadCredentialsException expected) {
188 assertEquals("The presented CasAuthenticationToken does not contain the expected key",
189 expected.getMessage());
190 }
191 }
192
193 public void testDetectsMissingAuthoritiesPopulator()
194 throws Exception {
195 CasAuthenticationProvider cap = new CasAuthenticationProvider();
196 cap.setCasProxyDecider(new MockProxyDecider());
197 cap.setKey("qwerty");
198 cap.setStatelessTicketCache(new MockStatelessTicketCache());
199 cap.setTicketValidator(new MockTicketValidator(true));
200
201 try {
202 cap.afterPropertiesSet();
203 fail("Should have thrown IllegalArgumentException");
204 } catch (IllegalArgumentException expected) {
205 assertEquals("A casAuthoritiesPopulator must be set",
206 expected.getMessage());
207 }
208 }
209
210 public void testDetectsMissingKey() throws Exception {
211 CasAuthenticationProvider cap = new CasAuthenticationProvider();
212 cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
213 cap.setCasProxyDecider(new MockProxyDecider());
214 cap.setStatelessTicketCache(new MockStatelessTicketCache());
215 cap.setTicketValidator(new MockTicketValidator(true));
216
217 try {
218 cap.afterPropertiesSet();
219 fail("Should have thrown IllegalArgumentException");
220 } catch (IllegalArgumentException expected) {
221 assertEquals("A Key is required so CasAuthenticationProvider can identify tokens it previously authenticated",
222 expected.getMessage());
223 }
224 }
225
226 public void testDetectsMissingProxyDecider() throws Exception {
227 CasAuthenticationProvider cap = new CasAuthenticationProvider();
228 cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
229 cap.setKey("qwerty");
230 cap.setStatelessTicketCache(new MockStatelessTicketCache());
231 cap.setTicketValidator(new MockTicketValidator(true));
232
233 try {
234 cap.afterPropertiesSet();
235 fail("Should have thrown IllegalArgumentException");
236 } catch (IllegalArgumentException expected) {
237 assertEquals("A casProxyDecider must be set", expected.getMessage());
238 }
239 }
240
241 public void testDetectsMissingStatelessTicketCache()
242 throws Exception {
243 CasAuthenticationProvider cap = new CasAuthenticationProvider();
244 cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
245 cap.setCasProxyDecider(new MockProxyDecider());
246 cap.setKey("qwerty");
247 cap.setTicketValidator(new MockTicketValidator(true));
248
249 try {
250 cap.afterPropertiesSet();
251 fail("Should have thrown IllegalArgumentException");
252 } catch (IllegalArgumentException expected) {
253 assertEquals("A statelessTicketCache must be set",
254 expected.getMessage());
255 }
256 }
257
258 public void testDetectsMissingTicketValidator() throws Exception {
259 CasAuthenticationProvider cap = new CasAuthenticationProvider();
260 cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
261 cap.setCasProxyDecider(new MockProxyDecider(true));
262 cap.setKey("qwerty");
263 cap.setStatelessTicketCache(new MockStatelessTicketCache());
264
265 try {
266 cap.afterPropertiesSet();
267 fail("Should have thrown IllegalArgumentException");
268 } catch (IllegalArgumentException expected) {
269 assertEquals("A ticketValidator must be set", expected.getMessage());
270 }
271 }
272
273 public void testGettersSetters() throws Exception {
274 CasAuthenticationProvider cap = new CasAuthenticationProvider();
275 cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
276 cap.setCasProxyDecider(new MockProxyDecider());
277 cap.setKey("qwerty");
278 cap.setStatelessTicketCache(new MockStatelessTicketCache());
279 cap.setTicketValidator(new MockTicketValidator(true));
280 cap.afterPropertiesSet();
281
282 assertTrue(cap.getCasAuthoritiesPopulator() != null);
283 assertTrue(cap.getCasProxyDecider() != null);
284 assertEquals("qwerty", cap.getKey());
285 assertTrue(cap.getStatelessTicketCache() != null);
286 assertTrue(cap.getTicketValidator() != null);
287 }
288
289 public void testIgnoresClassesItDoesNotSupport() throws Exception {
290 CasAuthenticationProvider cap = new CasAuthenticationProvider();
291 cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
292 cap.setCasProxyDecider(new MockProxyDecider());
293 cap.setKey("qwerty");
294 cap.setStatelessTicketCache(new MockStatelessTicketCache());
295 cap.setTicketValidator(new MockTicketValidator(true));
296 cap.afterPropertiesSet();
297
298 TestingAuthenticationToken token = new TestingAuthenticationToken("user",
299 "password",
300 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A")});
301 assertFalse(cap.supports(TestingAuthenticationToken.class));
302
303
304 assertEquals(null, cap.authenticate(token));
305 }
306
307 public void testIgnoresUsernamePasswordAuthenticationTokensWithoutCasIdentifiersAsPrincipal()
308 throws Exception {
309 CasAuthenticationProvider cap = new CasAuthenticationProvider();
310 cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
311 cap.setCasProxyDecider(new MockProxyDecider());
312 cap.setKey("qwerty");
313 cap.setStatelessTicketCache(new MockStatelessTicketCache());
314 cap.setTicketValidator(new MockTicketValidator(true));
315 cap.afterPropertiesSet();
316
317 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("some_normal_user",
318 "password",
319 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A")});
320 assertEquals(null, cap.authenticate(token));
321 }
322
323 public void testSupports() {
324 CasAuthenticationProvider cap = new CasAuthenticationProvider();
325 assertTrue(cap.supports(UsernamePasswordAuthenticationToken.class));
326 assertTrue(cap.supports(CasAuthenticationToken.class));
327 }
328
329 private UserDetails makeUserDetails() {
330 return new User("user", "password", true, true, true, true,
331 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
332 "ROLE_TWO")});
333 }
334
335
336
337 private class MockAuthoritiesPopulator implements CasAuthoritiesPopulator {
338 public UserDetails getUserDetails(String casUserId)
339 throws AuthenticationException {
340 return new User("user", "password", true, true, true, true,
341 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A"), new GrantedAuthorityImpl(
342 "ROLE_B")});
343 }
344 }
345
346 private class MockProxyDecider implements CasProxyDecider {
347 private boolean acceptProxy;
348
349 public MockProxyDecider(boolean acceptProxy) {
350 this.acceptProxy = acceptProxy;
351 }
352
353 private MockProxyDecider() {
354 super();
355 }
356
357 public void confirmProxyListTrusted(List proxyList)
358 throws ProxyUntrustedException {
359 if (acceptProxy) {
360 return;
361 } else {
362 throw new ProxyUntrustedException("As requested from mock");
363 }
364 }
365 }
366
367 private class MockStatelessTicketCache implements StatelessTicketCache {
368 private Map cache = new HashMap();
369
370 public CasAuthenticationToken getByTicketId(String serviceTicket) {
371 return (CasAuthenticationToken) cache.get(serviceTicket);
372 }
373
374 public void putTicketInCache(CasAuthenticationToken token) {
375 cache.put(token.getCredentials().toString(), token);
376 }
377
378 public void removeTicketFromCache(CasAuthenticationToken token) {
379 throw new UnsupportedOperationException(
380 "mock method not implemented");
381 }
382
383 public void removeTicketFromCache(String serviceTicket) {
384 throw new UnsupportedOperationException(
385 "mock method not implemented");
386 }
387 }
388
389 private class MockTicketValidator extends AbstractTicketValidator {
390 private boolean returnTicket;
391
392 public MockTicketValidator(boolean returnTicket) {
393 this.returnTicket = returnTicket;
394 }
395
396 private MockTicketValidator() {
397 super();
398 }
399
400 public TicketResponse confirmTicketValid(String serviceTicket)
401 throws AuthenticationException {
402 if (returnTicket) {
403 List list = new Vector();
404 list.add("https://localhost/portal/j_acegi_cas_security_check");
405
406 return new TicketResponse("marissa", list,
407 "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt");
408 }
409
410 throw new BadCredentialsException("As requested from mock");
411 }
412 }
413 }