View Javadoc

1   package com.atlassian.asap.core.server.springsecurity;
2   
3   import com.atlassian.asap.api.Jwt;
4   import com.atlassian.asap.api.JwtBuilder;
5   import com.atlassian.asap.core.exception.InvalidHeaderException;
6   import com.atlassian.asap.core.exception.JwtParseException;
7   import com.atlassian.asap.core.exception.PublicKeyNotFoundException;
8   import com.atlassian.asap.core.exception.PublicKeyRetrievalException;
9   import com.atlassian.asap.core.validator.JwtValidator;
10  import com.atlassian.asap.core.validator.ValidatedKeyId;
11  import org.junit.Before;
12  import org.junit.Rule;
13  import org.junit.Test;
14  import org.mockito.Mock;
15  import org.mockito.junit.MockitoJUnit;
16  import org.mockito.junit.MockitoRule;
17  import org.springframework.security.authentication.AuthenticationServiceException;
18  import org.springframework.security.authentication.BadCredentialsException;
19  import org.springframework.security.authentication.InsufficientAuthenticationException;
20  import org.springframework.security.core.Authentication;
21  import org.springframework.security.core.AuthenticationException;
22  import org.springframework.security.core.GrantedAuthority;
23  
24  import java.io.Serializable;
25  import java.util.Collection;
26  import java.util.Collections;
27  import java.util.Optional;
28  
29  import static org.hamcrest.MatcherAssert.assertThat;
30  import static org.hamcrest.Matchers.contains;
31  import static org.hamcrest.Matchers.instanceOf;
32  import static org.junit.Assert.assertEquals;
33  import static org.mockito.Mockito.when;
34  
35  public class AsapAuthenticationProviderTest {
36      private static final String SERIALISED_TOKEN = "my-token";
37      private static final Jwt JWT = JwtBuilder.newJwt().keyId("key-id").issuer("issuer").audience("audience").build();
38  
39      @Rule
40      public MockitoRule mockitoRule = MockitoJUnit.rule();
41  
42      @Mock
43      private Authentication authentication;
44  
45      @Mock
46      private JwtValidator jwtValidator;
47  
48      @Mock
49      private GrantedAuthority grantedAuthority;
50  
51      private ValidatedKeyId validatedKeyId;
52  
53      @Before
54      public void prepareValidatedKey() throws InvalidHeaderException {
55          validatedKeyId = ValidatedKeyId.validate("key-id");
56      }
57  
58      @Before
59      public void prepareAuthenticationContext() {
60          when(authentication.getCredentials()).thenReturn(SERIALISED_TOKEN);
61      }
62  
63      @Test(expected = BadCredentialsException.class)
64      public void shouldFailIfTokenIsInvalid() throws Exception {
65          when(jwtValidator.readAndValidate(SERIALISED_TOKEN))
66                  .thenThrow(new JwtParseException("token is invalid"));
67  
68          createSut().authenticate(authentication);
69      }
70  
71      @Test(expected = AuthenticationServiceException.class)
72      public void shouldFailIfRetrievingPublicKeyFails() throws Exception {
73  
74          when(jwtValidator.readAndValidate(SERIALISED_TOKEN))
75                  .thenThrow(new PublicKeyRetrievalException("key repo fail", validatedKeyId, null));
76  
77          createSut().authenticate(authentication);
78      }
79  
80      @Test(expected = BadCredentialsException.class)
81      public void shouldFailIfPublicKeyCannotBeFound() throws Exception {
82  
83          when(jwtValidator.readAndValidate(SERIALISED_TOKEN))
84                  .thenThrow(new PublicKeyNotFoundException("public key not found", validatedKeyId, null));
85  
86          createSut().authenticate(authentication);
87      }
88  
89      @Test
90      public void shouldReturnDefaultGrantedAuthoritiesAndSerializableJwtIfValidationSucceeds() throws Exception {
91          when(jwtValidator.readAndValidate(SERIALISED_TOKEN)).thenReturn(JWT);
92  
93          Authentication authenticationResult = createSut().authenticate(authentication);
94          assertEquals("issuer", authenticationResult.getPrincipal()); // token has no explicit subject
95          assertEquals(JWT, authenticationResult.getCredentials());
96          assertThat(authenticationResult.getCredentials(), instanceOf(Serializable.class));
97          assertThat(authenticationResult.getAuthorities(), contains(grantedAuthority));
98      }
99  
100     @Test(expected = InsufficientAuthenticationException.class)
101     public void shouldFailIfPrincipalValidationFails() throws Exception {
102         AsapAuthenticationProvider sut = new AsapAuthenticationProvider(jwtValidator) {
103             @Override
104             protected Collection<GrantedAuthority> getGrantedAuthorities(Jwt validJwt) throws AuthenticationException {
105                 throw new InsufficientAuthenticationException("no, you cannot authenticate");
106             }
107         };
108 
109         when(jwtValidator.readAndValidate(SERIALISED_TOKEN)).thenReturn(JWT);
110 
111         sut.authenticate(authentication);
112     }
113 
114     @Test
115     public void effectiveSubjectIsTheSubjectIfPresent() throws Exception {
116         Jwt jwtWithSubject = JwtBuilder.copyJwt(JWT).subject(Optional.of("explicit-subject")).build();
117         assertEquals("explicit-subject", AsapAuthenticationProvider.effectiveSubject(jwtWithSubject));
118     }
119 
120     @Test
121     public void effectiveSubjectIsTheIssuerIfSubjectNotPresent() throws Exception {
122         Jwt jwtWithoutSubject = JwtBuilder.copyJwt(JWT).subject(Optional.<String>empty()).build();
123         assertEquals(JWT.getClaims().getIssuer(), AsapAuthenticationProvider.effectiveSubject(jwtWithoutSubject));
124     }
125 
126     private AsapAuthenticationProvider createSut() {
127         return new AsapAuthenticationProvider(jwtValidator, Collections.singleton(grantedAuthority));
128     }
129 }