View Javadoc

1   package com.atlassian.asap.core.server.http;
2   
3   import com.atlassian.asap.api.JwsHeader;
4   import com.atlassian.asap.api.Jwt;
5   import com.atlassian.asap.api.JwtClaims;
6   import com.atlassian.asap.api.exception.CannotRetrieveKeyException;
7   import com.atlassian.asap.api.exception.PermanentAuthenticationFailedException;
8   import com.atlassian.asap.api.exception.TransientAuthenticationFailedException;
9   import com.atlassian.asap.api.server.http.RequestAuthenticator;
10  import com.atlassian.asap.core.exception.InvalidClaimException;
11  import com.atlassian.asap.core.exception.MissingRequiredClaimException;
12  import com.atlassian.asap.core.exception.MissingRequiredHeaderException;
13  import com.atlassian.asap.core.exception.SignatureMismatchException;
14  import com.atlassian.asap.core.serializer.JwtSerializer;
15  import com.atlassian.asap.core.validator.JwtValidator;
16  import org.junit.Before;
17  import org.junit.Rule;
18  import org.junit.Test;
19  import org.junit.rules.ExpectedException;
20  import org.junit.runner.RunWith;
21  import org.mockito.Mock;
22  import org.mockito.runners.MockitoJUnitRunner;
23  
24  import java.util.Optional;
25  
26  import static org.junit.Assert.assertEquals;
27  import static org.mockito.Mockito.verify;
28  import static org.mockito.Mockito.verifyZeroInteractions;
29  import static org.mockito.Mockito.when;
30  
31  @RunWith(MockitoJUnitRunner.class)
32  public class RequestAuthenticatorImplTest {
33      private static final String SERIALIZED_JWT = "my.jwt.token";
34  
35      @Rule
36      public final ExpectedException expectedException = ExpectedException.none();
37  
38      @Mock
39      private JwtValidator jwtValidator;
40      @Mock
41      private JwtSerializer jwtSerializer;
42      @Mock
43      private Jwt jwt;
44  
45      private RequestAuthenticator requestAuthenticator;
46  
47      @Before
48      public void setUp() throws Exception {
49          requestAuthenticator = new RequestAuthenticatorImpl(jwtValidator);
50      }
51  
52      @Test(expected = PermanentAuthenticationFailedException.class)
53      public void shouldFailIfHeaderNotInRightFormat() throws Exception {
54          requestAuthenticator.authenticateRequest("a bad authorisation header");
55          verifyZeroInteractions(jwtValidator);
56      }
57  
58      @Test
59      public void shouldFailIfValidationFails() throws Exception {
60          when(jwtValidator.readAndValidate(SERIALIZED_JWT)).thenThrow(new SignatureMismatchException("Couldn't validate token"));
61          when(jwtValidator.determineUnverifiedIssuer(SERIALIZED_JWT)).thenReturn(Optional.of("some-service"));
62  
63          expectedException.expect(PermanentAuthenticationFailedException.class);
64          expectedException.expectMessage("Failed to authenticate request from some-service (issuer not verified): SignatureMismatchException");
65  
66          requestAuthenticator.authenticateRequest("Bearer " + SERIALIZED_JWT);
67      }
68  
69      @Test
70      public void shouldIncludeFailingClaims() throws Exception {
71          when(jwtValidator.readAndValidate(SERIALIZED_JWT)).thenThrow(new InvalidClaimException(JwtClaims.RegisteredClaim.EXPIRY, "Token is expired!"));
72          when(jwtValidator.determineUnverifiedIssuer(SERIALIZED_JWT)).thenReturn(Optional.of("some-service"));
73  
74          expectedException.expect(PermanentAuthenticationFailedException.class);
75          expectedException.expectMessage("Failed to authenticate request from some-service (issuer not verified): InvalidClaimException - EXPIRY");
76  
77          requestAuthenticator.authenticateRequest("Bearer " + SERIALIZED_JWT);
78      }
79  
80      @Test
81      public void shouldIncludeMissingClaim() throws Exception {
82          when(jwtValidator.readAndValidate(SERIALIZED_JWT)).thenThrow(new MissingRequiredClaimException(JwtClaims.RegisteredClaim.EXPIRY));
83          when(jwtValidator.determineUnverifiedIssuer(SERIALIZED_JWT)).thenReturn(Optional.empty());
84  
85          expectedException.expect(PermanentAuthenticationFailedException.class);
86          expectedException.expectMessage("Failed to authenticate request from unknown issuer: MissingRequiredClaimException - EXPIRY");
87  
88          requestAuthenticator.authenticateRequest("Bearer " + SERIALIZED_JWT);
89      }
90  
91      @Test
92      public void shouldIncludeMissingHeader() throws Exception {
93          when(jwtValidator.readAndValidate(SERIALIZED_JWT)).thenThrow(new MissingRequiredHeaderException(JwsHeader.Header.KEY_ID));
94          when(jwtValidator.determineUnverifiedIssuer(SERIALIZED_JWT)).thenReturn(Optional.empty());
95  
96          expectedException.expect(PermanentAuthenticationFailedException.class);
97          expectedException.expectMessage("Failed to authenticate request from unknown issuer: MissingRequiredHeaderException - KEY_ID");
98  
99          requestAuthenticator.authenticateRequest("Bearer " + SERIALIZED_JWT);
100     }
101 
102     @Test
103     public void shouldFailWithTransientErrorIfCannotRetrieveKey() throws Exception {
104         when(jwtValidator.readAndValidate(SERIALIZED_JWT)).thenThrow(new CannotRetrieveKeyException("500 error from key server"));
105         when(jwtValidator.determineUnverifiedIssuer(SERIALIZED_JWT)).thenReturn(Optional.empty());
106 
107         expectedException.expect(TransientAuthenticationFailedException.class);
108         expectedException.expectMessage("Failed to retrieve the key required to authenticate request from unknown issuer: 500 error from key server");
109 
110         requestAuthenticator.authenticateRequest("Bearer " + SERIALIZED_JWT);
111     }
112 
113     @Test
114     public void shouldReturnJwtIfSuccessful() throws Exception {
115         when(jwtValidator.readAndValidate(SERIALIZED_JWT)).thenReturn(jwt);
116 
117         Jwt validatedToken = requestAuthenticator.authenticateRequest("Bearer " + SERIALIZED_JWT);
118 
119         assertEquals(jwt, validatedToken);
120 
121         verify(jwtValidator).readAndValidate(SERIALIZED_JWT);
122     }
123 }