    1   /* Copyright 2004 Acegi Technology Pty Limited
    2    *
    3    * Licensed under the Apache License, Version 2.0 (the "License");
    4    * you may not use this file except in compliance with the License.
    5    * You may obtain a copy of the License at
    6    *
    7    *     http://www.apache.org/licenses/LICENSE-2.0
    8    *
    9    * Unless required by applicable law or agreed to in writing, software
    10   * distributed under the License is distributed on an "AS IS" BASIS,
    11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12   * See the License for the specific language governing permissions and
    13   * limitations under the License.
    14   */
    15
    16  package org.acegisecurity.providers.jaas;
    17
    18  import junit.framework.TestCase;
    19  import org.acegisecurity.*;
    20  import org.acegisecurity.context.HttpSessionContextIntegrationFilter;
    21  import org.acegisecurity.context.SecurityContextImpl;
    22  import org.acegisecurity.ui.session.HttpSessionDestroyedEvent;
    23  import org.acegisecurity.providers.TestingAuthenticationToken;
    24  import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
    25  import org.springframework.context.ApplicationContext;
    26  import org.springframework.context.support.ClassPathXmlApplicationContext;
    27  import org.springframework.mock.web.MockHttpSession;
    28
    29  import javax.security.auth.login.LoginException;
    30  import javax.security.auth.login.LoginContext;
    31  import java.net.URL;
    32  import java.security.Security;
    33  import java.util.Arrays;
    34  import java.util.List;
    35
    36
    37  /***
    38   * Tests for the JaasAuthenticationProvider
    39   *
    40   * @author Ray Krueger
    41   * @version $Id: JaasAuthenticationProviderTests.java,v 1.11 2005/11/17 00:55:47 benalex Exp $
    42   */
    43  public class JaasAuthenticationProviderTests extends TestCase {
    44      //~ Instance fields ========================================================
    45
    46      private ApplicationContext context;
    47      private JaasAuthenticationProvider jaasProvider;
    48      private JaasEventCheck eventCheck;
    49
    50      //~ Methods ================================================================
    51
    52      public void testBadPassword() {
    53          try {
    54              jaasProvider.authenticate(new UsernamePasswordAuthenticationToken("user", "asdf"));
    55              fail("LoginException should have been thrown for the bad password");
    56          } catch (AuthenticationException e) {
    57          }
    58
    59          assertNotNull("Failure event not fired", eventCheck.failedEvent);
    60          assertNotNull("Failure event exception was null",
    61                  eventCheck.failedEvent.getException());
    62          assertNull("Success event was fired", eventCheck.successEvent);
    63      }
    64
    65      public void testBadUser() {
    66          try {
    67              jaasProvider.authenticate(new UsernamePasswordAuthenticationToken("asdf", "password"));
    68              fail("LoginException should have been thrown for the bad user");
    69          } catch (AuthenticationException e) {
    70          }
    71
    72          assertNotNull("Failure event not fired", eventCheck.failedEvent);
    73          assertNotNull("Failure event exception was null",
    74                  eventCheck.failedEvent.getException());
    75          assertNull("Success event was fired", eventCheck.successEvent);
    76      }
    77
    78      public void testConfigurationLoop() throws Exception {
    79          String resName = "/" + getClass().getName().replace('.', '/') + ".conf";
    80          URL url = getClass().getResource(resName);
    81
    82          Security.setProperty("login.config.url.1", url.toString());
    83
    84          setUp();
    85          testFull();
    86      }
    87
    88      public void testDetectsMissingLoginConfig() throws Exception {
    89          JaasAuthenticationProvider myJaasProvider = new JaasAuthenticationProvider();
    90          myJaasProvider.setApplicationContext(context);
    91          myJaasProvider.setAuthorityGranters(jaasProvider.getAuthorityGranters());
    92          myJaasProvider.setCallbackHandlers(jaasProvider.getCallbackHandlers());
    93          myJaasProvider.setLoginContextName(jaasProvider.getLoginContextName());
    94
    95          try {
    96              myJaasProvider.afterPropertiesSet();
    97              fail("Should have thrown ApplicationContextException");
    98          } catch (IllegalArgumentException expected) {
    99              assertTrue(expected.getMessage().startsWith("loginConfig must be set on"));
    100         }
    101     }
    102
    103     public void testDetectsMissingLoginContextName() throws Exception {
    104         JaasAuthenticationProvider myJaasProvider = new JaasAuthenticationProvider();
    105         myJaasProvider.setApplicationContext(context);
    106         myJaasProvider.setAuthorityGranters(jaasProvider.getAuthorityGranters());
    107         myJaasProvider.setCallbackHandlers(jaasProvider.getCallbackHandlers());
    108         myJaasProvider.setLoginConfig(jaasProvider.getLoginConfig());
    109         myJaasProvider.setLoginContextName(null);
    110
    111         try {
    112             myJaasProvider.afterPropertiesSet();
    113             fail("Should have thrown IllegalArgumentException");
    114         } catch (IllegalArgumentException expected) {
    115             assertTrue(expected.getMessage().startsWith("loginContextName must be set on"));
    116         }
    117
    118         myJaasProvider.setLoginContextName("");
    119
    120         try {
    121             myJaasProvider.afterPropertiesSet();
    122             fail("Should have thrown IllegalArgumentException");
    123         } catch (IllegalArgumentException expected) {
    124             assertTrue(expected.getMessage().startsWith("loginContextName must be set on"));
    125         }
    126     }
    127
    128     public void testFull() throws Exception {
    129         GrantedAuthorityImpl role1 = new GrantedAuthorityImpl("ROLE_1");
    130         GrantedAuthorityImpl role2 = new GrantedAuthorityImpl("ROLE_2");
    131
    132         GrantedAuthority[] defaultAuths = new GrantedAuthority[]{role1, role2, };
    133
    134         UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user",
    135                 "password", defaultAuths);
    136
    137         assertTrue(jaasProvider.supports(UsernamePasswordAuthenticationToken.class));
    138
    139         Authentication auth = jaasProvider.authenticate(token);
    140
    141         assertNotNull(jaasProvider.getAuthorityGranters());
    142         assertNotNull(jaasProvider.getCallbackHandlers());
    143         assertNotNull(jaasProvider.getLoginConfig());
    144         assertNotNull(jaasProvider.getLoginContextName());
    145
    146         List list = Arrays.asList(auth.getAuthorities());
    147
    148         assertTrue("GrantedAuthorities should contain ROLE_TEST1",
    149                 list.contains(new GrantedAuthorityImpl("ROLE_TEST1")));
    150
    151         assertTrue("GrantedAuthorities should contain ROLE_TEST2",
    152                 list.contains(new GrantedAuthorityImpl("ROLE_TEST2")));
    153
    154         assertTrue("GrantedAuthorities should contain ROLE_1",
    155                 list.contains(role1));
    156
    157         assertTrue("GrantedAuthorities should contain ROLE_2",
    158                 list.contains(role2));
    159
    160         boolean foundit = false;
    161
    162         for (int i = 0; i < list.size(); i++) {
    163             Object obj = list.get(i);
    164
    165             if (obj instanceof JaasGrantedAuthority) {
    166                 JaasGrantedAuthority grant = (JaasGrantedAuthority) obj;
    167                 assertNotNull("Principal was null on JaasGrantedAuthority",
    168                         grant.getPrincipal());
    169                 foundit = true;
    170             }
    171         }
    172
    173         assertTrue("Could not find a JaasGrantedAuthority", foundit);
    174
    175         assertNotNull("Success event not fired", eventCheck.successEvent);
    176         assertEquals("Auth objects are not equal", auth,
    177                 eventCheck.successEvent.getAuthentication());
    178
    179         assertNull("Failure event was fired", eventCheck.failedEvent);
    180     }
    181
    182     public void testLoginExceptionResolver() {
    183         assertNotNull(jaasProvider.getLoginExceptionResolver());
    184         jaasProvider.setLoginExceptionResolver(new LoginExceptionResolver() {
    185             public AcegiSecurityException resolveException(LoginException e) {
    186                 return new LockedException("This is just a test!");
    187             }
    188         });
    189
    190         try {
    191             jaasProvider.authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
    192         } catch (LockedException e) {
    193         } catch (Exception e) {
    194             fail("LockedException should have been thrown and caught");
    195         }
    196     }
    197
    198     public void testNullDefaultAuthorities() {
    199         UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user",
    200                 "password", null);
    201
    202         assertTrue(jaasProvider.supports(UsernamePasswordAuthenticationToken.class));
    203
    204         Authentication auth = jaasProvider.authenticate(token);
    205         assertTrue("Only ROLE_TEST1 and ROLE_TEST2 should have been returned",
    206                 auth.getAuthorities().length == 2);
    207     }
    208
    209     public void testGetApplicationContext() throws Exception {
    210         assertNotNull(jaasProvider.getApplicationContext());
    211     }
    212
    213     public void testUnsupportedAuthenticationObjectReturnsNull() {
    214         assertNull(jaasProvider.authenticate(new TestingAuthenticationToken("foo", "bar",
    215                 new GrantedAuthority[]{})));
    216     }
    217
    218     public void testLogout() throws Exception {
    219
    220         MockLoginContext loginContext = new MockLoginContext(jaasProvider.getLoginContextName());
    221
    222         JaasAuthenticationToken token = new JaasAuthenticationToken(null, null, loginContext);
    223
    224         SecurityContextImpl context = new SecurityContextImpl();
    225         context.setAuthentication(token);
    226
    227         MockHttpSession mockSession = new MockHttpSession();
    228         mockSession.setAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY, context);
    229
    230         jaasProvider.onApplicationEvent(new HttpSessionDestroyedEvent(mockSession));
    231
    232         assertTrue(loginContext.loggedOut);
    233     }
    234
    235     protected void setUp() throws Exception {
    236         String resName = "/" + getClass().getName().replace('.', '/') + ".xml";
    237         context = new ClassPathXmlApplicationContext(resName);
    238         eventCheck = (JaasEventCheck) context.getBean("eventCheck");
    239         jaasProvider = (JaasAuthenticationProvider) context.getBean("jaasAuthenticationProvider");
    240     }
    241
    242     private static class MockLoginContext extends LoginContext {
    243
    244         boolean loggedOut = false;
    245
    246         public MockLoginContext(String loginModule) throws LoginException {
    247             super(loginModule);
    248         }
    249
    250         public void logout() throws LoginException {
    251             this.loggedOut = true;
    252         }
    253     }
    254 }