1 package com.atlassian.plugins.rest.common.security.jersey;
2
3 import com.atlassian.plugins.rest.common.security.XsrfCheckFailedException;
4 import com.atlassian.sal.api.web.context.HttpContext;
5 import com.atlassian.sal.core.xsrf.IndependentXsrfTokenAccessor;
6 import com.atlassian.sal.core.xsrf.IndependentXsrfTokenValidator;
7 import com.atlassian.sal.core.xsrf.XsrfRequestValidatorImpl;
8 import com.google.common.collect.ImmutableList;
9 import com.sun.jersey.spi.container.ContainerRequest;
10 import org.junit.Before;
11 import org.junit.Test;
12 import org.junit.runner.RunWith;
13 import org.mockito.Mock;
14 import org.mockito.runners.MockitoJUnitRunner;
15
16 import javax.servlet.http.HttpServletRequest;
17 import javax.ws.rs.HttpMethod;
18 import javax.ws.rs.core.MediaType;
19 import java.net.URI;
20 import java.util.Arrays;
21
22 import static com.atlassian.plugins.rest.common.security.jersey.TestXsrfResourceFilter.addTokenHeaderToRequest;
23 import static org.mockito.Mockito.when;
24
25 @RunWith(MockitoJUnitRunner.class)
26 public class TestOriginBasedXsrfResourceFilter {
27 private static final String IE_8_UA = "Mozilla/4.0 (compatible; MSIE 8.0" +
28 "; Windows NT 6.0; Trident/4.0)";
29 private static final String IE_10_UA = "Mozilla/5.0 (compatible; " +
30 "MSIE 10.0; Windows NT 6.2; Trident/6.0)";
31 private static final String IE_11_UA = "Mozilla/5.0 " +
32 "(Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko";
33 private static final String CHROME_32_UA = "Mozilla/5.0 (Windows NT 6.2;" +
34 " Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " +
35 "Chrome/32.0.1667.0 Safari/537.36";
36
37 private static final ImmutableList<String> IDEMPOTENT_METHODS = ImmutableList.of(
38 HttpMethod.GET, HttpMethod.HEAD, HttpMethod.OPTIONS, "TRACE");
39
40 private XsrfResourceFilter xsrfResourceFilter;
41 @Mock
42 private ContainerRequest request;
43 @Mock
44 private HttpContext httpContext;
45 @Mock
46 private HttpServletRequest httpServletRequest;
47
48 @Before
49 public void setUp() throws Exception {
50 xsrfResourceFilter = new OriginBasedXsrfResourceFilter();
51 xsrfResourceFilter.setXsrfRequestValidator(
52 new XsrfRequestValidatorImpl(
53 new IndependentXsrfTokenValidator(
54 new IndependentXsrfTokenAccessor())));
55 when(request.getRequestUri()).thenReturn(new URI("http://default.com"));
56 when(request.getPath()).thenReturn("/example");
57 when(request.getMethod()).thenReturn("POST");
58 when(httpContext.getRequest()).thenReturn(httpServletRequest);
59 xsrfResourceFilter.setHttpContext(httpContext);
60 }
61
62 @Test
63 public void browserIdempotentRequestNotBlocked() throws Exception {
64 setBrowserUserAgentInRequest(request);
65 for (String method : IDEMPOTENT_METHODS) {
66 when(request.getMethod()).thenReturn(method);
67 xsrfResourceFilter.filter(request);
68 }
69 }
70
71 @Test
72 public void nonBrowserIdempotentRequestNotBlocked() throws Exception {
73 for (String method : IDEMPOTENT_METHODS) {
74 when(request.getMethod()).thenReturn(method);
75 xsrfResourceFilter.filter(request);
76 }
77 }
78
79 @Test(expected = XsrfCheckFailedException.class)
80 public void browserPostJsonRequestBlocked() throws Exception {
81 when(request.getMethod()).thenReturn("POST");
82 filterBrowserJsonRequest(request);
83 }
84
85 @Test
86 public void browserPutJsonRequestNotBlocked() throws Exception {
87 when(request.getMethod()).thenReturn("PUT");
88 filterBrowserJsonRequest(request);
89 }
90
91 @Test
92 public void browserDeleteJsonRequestNotBlocked() throws Exception {
93 when(request.getMethod()).thenReturn("DELETE");
94 filterBrowserJsonRequest(request);
95 }
96
97 @Test
98 public void nonBrowserPostJsonRequestNotBlocked() throws Exception {
99 setJsonContentTypeForRequest(request);
100 xsrfResourceFilter.filter(request);
101 }
102
103 @Test(expected = XsrfCheckFailedException.class)
104 public void NonIEBrowserPostJsonRequestWithTokenHeaderBlocked()
105 throws Exception {
106 addTokenHeaderToRequest(httpServletRequest, XsrfResourceFilter.NO_CHECK);
107 setJsonContentTypeForRequest(request);
108 setBrowserUserAgentInRequest(request, CHROME_32_UA);
109 xsrfResourceFilter.filter(request);
110 }
111
112 @Test
113 public void internetExplorerBrowserPostJsonRequestWithTokenHeaderNotBlocked()
114 throws Exception {
115 addTokenHeaderToRequest(httpServletRequest, XsrfResourceFilter.NO_CHECK);
116 setJsonContentTypeForRequest(request);
117 for (String userAgent : Arrays.asList(IE_8_UA, IE_10_UA, IE_11_UA)) {
118 setBrowserUserAgentInRequest(request, userAgent);
119 xsrfResourceFilter.filter(request);
120 }
121 }
122
123 @Test(expected = XsrfCheckFailedException.class)
124 public void browserPostNoContentTypeRequestBlocked() throws Exception {
125 setBrowserUserAgentInRequest(request);
126 setRequestContentType(request, null);
127 xsrfResourceFilter.filter(request);
128 }
129
130 @Test
131 public void nonBrowserPostNoContentTypeRequestNotBlocked() throws Exception {
132 setRequestContentType(request, null);
133 xsrfResourceFilter.filter(request);
134 }
135
136 @Test
137 public void browserPostXsrfContentTypeRequestNotBlocked() throws Exception {
138 setBrowserUserAgentInRequest(request);
139 setXsrfableContentType(request);
140 xsrfResourceFilter.filter(request);
141 }
142
143 @Test
144 public void nonBrowserPostXsrfContentTypeRequestNotBlocked() throws Exception {
145 setXsrfableContentType(request);
146 xsrfResourceFilter.filter(request);
147 }
148
149 @Test
150 public void browserDeleteXsrfContentTypeRequestNotBlocked() throws Exception {
151 when(request.getMethod()).thenReturn("DELETE");
152 setBrowserUserAgentInRequest(request);
153 setXsrfableContentType(request);
154 xsrfResourceFilter.filter(request);
155 }
156
157 private void filterBrowserJsonRequest(ContainerRequest request)
158 throws Exception {
159 setBrowserUserAgentInRequest(request);
160 setJsonContentTypeForRequest(request);
161 xsrfResourceFilter.filter(request);
162 }
163
164 static void setXsrfableContentType(ContainerRequest request) {
165 setRequestContentType(request, MediaType.TEXT_PLAIN_TYPE);
166 }
167
168 private static void setJsonContentTypeForRequest(ContainerRequest request) {
169 setRequestContentType(request, MediaType.APPLICATION_JSON_TYPE);
170 }
171
172 private static void setRequestContentType(ContainerRequest request,
173 MediaType mediaType) {
174 when(request.getMediaType()).thenReturn(mediaType);
175 }
176
177 static void setBrowserUserAgentInRequest(ContainerRequest request) {
178 setBrowserUserAgentInRequest(request, CHROME_32_UA);
179 }
180
181 private static void setBrowserUserAgentInRequest(ContainerRequest request, String userAgent) {
182 when(request.getHeaderValue("User-Agent")).thenReturn(userAgent);
183 }
184
185 }