1 package com.atlassian.security.auth.trustedapps.filter;
2
3 import com.atlassian.security.auth.trustedapps.*;
4 import junit.framework.TestCase;
5
6 import javax.servlet.http.HttpServletRequest;
7 import javax.servlet.http.HttpServletResponse;
8 import java.security.Principal;
9 import java.security.PublicKey;
10
11 public class TestTrustedAppAuthenticatorImpl extends TestCase
12 {
13 private static final String USER = "blad-de-blah-blah";
14 private final PublicKey publicKey = new PublicKey()
15 {
16 public String getAlgorithm()
17 {
18 return "algy";
19 }
20
21 public byte[] getEncoded()
22 {
23 return new byte[] { 4, 3, 2, 1 };
24 }
25
26 public String getFormat()
27 {
28 return "format";
29 }
30 };
31
32 private final TrustedApplicationsManager manager = new TrustedApplicationsManager()
33 {
34 final CurrentApplication me = new CurrentApplication()
35 {
36 public String getID()
37 {
38 return "me-id";
39 }
40
41 public PublicKey getPublicKey()
42 {
43 return publicKey;
44 }
45
46 public EncryptedCertificate encode(final String userName)
47 {
48 return new EncryptedCertificate()
49 {
50 public String getCertificate()
51 {
52 return userName;
53 }
54
55 public String getID()
56 {
57 return "me-id";
58 }
59
60 public String getMagicNumber()
61 {
62 return "1";
63 }
64
65 public Integer getProtocolVersion()
66 {
67 return new Integer(1);
68 }
69
70 public String getSecretKey()
71 {
72 return "secret";
73 }
74 };
75 }
76 };
77
78 public CurrentApplication getCurrentApplication()
79 {
80 return me;
81 }
82
83 public TrustedApplication getTrustedApplication(String id)
84 {
85 if (id.equals("me-id"))
86 {
87 return new TrustedApplication()
88 {
89 public ApplicationCertificate decode(EncryptedCertificate certificate, HttpServletRequest request) throws InvalidCertificateException
90 {
91 if (request.getHeader("ip-mismatch") != null)
92 {
93 throw new InvalidCertificateException(new InvalidRemoteAddressException(request.getRemoteAddr()));
94 }
95 if (request.getHeader("forward-mismatch") != null)
96 {
97 throw new InvalidCertificateException(new InvalidXForwardedForAddressException(request.getRemoteAddr()));
98 }
99 if (request.getHeader("url-mismatch") != null)
100 {
101 throw new InvalidCertificateException(new InvalidRequestUrlException(request.getPathInfo()));
102 }
103 if ("bad-cert".equals(certificate.getCertificate()))
104 {
105 throw new InvalidCertificateException(new SystemException("bad-cert", new NullPointerException("what a bad certificate!")));
106 }
107 return new DefaultApplicationCertificate("me-id", certificate.getCertificate(), System.currentTimeMillis());
108 }
109
110 public PublicKey getPublicKey()
111 {
112 return publicKey;
113 }
114
115 public String getID()
116 {
117 return "me-id";
118 }
119
120 public RequestConditions getRequestConditions()
121 {
122 return null;
123 }
124
125 public String getName()
126 {
127 return null;
128 }
129 };
130 }
131 return null;
132 }
133 };
134
135 private final Principal principal = new Principal()
136 {
137 public String getName()
138 {
139 return USER;
140 }
141 };
142
143 private final UserResolver resolver = new UserResolver()
144 {
145 public Principal resolve(ApplicationCertificate certificate)
146 {
147 return (certificate.getUserName().equals(principal.getName())) ? principal : null;
148 };
149 };
150
151 private final boolean[] canLogin = new boolean[] { true };
152 private final AuthenticationController authenticationController = new AuthenticationController()
153 {
154 public boolean shouldAttemptAuthentication(HttpServletRequest request)
155 {
156 return true;
157 }
158
159 public boolean canLogin(Principal user, HttpServletRequest request)
160 {
161 return canLogin[0];
162 }
163 };
164
165 private final Authenticator authenticator = new TrustedApplicationFilterAuthenticator(manager, resolver, authenticationController)
166 {
167 public Result authenticate(HttpServletRequest request, HttpServletResponse response)
168 {
169 return super.authenticate(ImmutableRequest.wrap(request), response);
170 }
171 };
172
173 protected void setUp() throws Exception
174 {
175 canLogin[0] = true;
176 }
177
178
179
180
181
182 public void testKnownAppProtocolVersion0() throws Exception
183 {
184 CurrentApplication me = manager.getCurrentApplication();
185 EncryptedCertificate cert = me.encode(USER);
186 MockRequest request = new MockTrustedAppRequestV0(cert);
187
188 Authenticator.Result result = authenticator.authenticate(request, new MockResponse());
189
190 assertNotNull(result);
191 assertEquals(Authenticator.Result.Status.SUCCESS, result.getStatus());
192 }
193
194 public void testKnownAppProtocolVersion1() throws Exception
195 {
196 CurrentApplication me = manager.getCurrentApplication();
197 EncryptedCertificate cert = me.encode(USER);
198 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
199
200 Authenticator.Result result = authenticator.authenticate(request, new MockResponse());
201
202 assertNotNull(result);
203 assertEquals(Authenticator.Result.Status.SUCCESS, result.getStatus());
204 assertNotNull(result.getUser());
205 }
206
207 public void testUnknownApp() throws Exception
208 {
209 EncryptedCertificate cert = new EncryptedCertificate()
210 {
211 public String getCertificate()
212 {
213 return "cert";
214 };
215
216 public String getID()
217 {
218 return "appId";
219 }
220
221 public String getMagicNumber()
222 {
223 return "majick";
224 }
225
226 public Integer getProtocolVersion()
227 {
228 return new Integer(1);
229 }
230
231 public String getSecretKey()
232 {
233 return "dis-is-a-sekrit";
234 }
235 };
236 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
237
238
239 Authenticator.Result result = authenticator.authenticate(request, new MockResponse());
240
241 assertNotNull(result);
242 assertEquals(Authenticator.Result.Status.FAILED, result.getStatus());
243 assertEquals("APP_UNKNOWN;\tUnknown Application: {0};\t[\"appId\"]", result.getMessage());
244 assertNull(result.getUser());
245 }
246
247 public void testBlankAppId() throws Exception
248 {
249 EncryptedCertificate cert = new EncryptedCertificate()
250 {
251 public String getCertificate()
252 {
253 return "cert";
254 };
255
256 public String getID()
257 {
258 return null;
259 }
260
261 public String getMagicNumber()
262 {
263 return "majick";
264 }
265
266 public Integer getProtocolVersion()
267 {
268 return new Integer(1);
269 }
270
271 public String getSecretKey()
272 {
273 return "dis-is-a-sekrit";
274 }
275 };
276 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
277
278
279 Authenticator.Result result = authenticator.authenticate(request, new MockResponse());
280
281 assertNotNull(result);
282 assertEquals(Authenticator.Result.Status.ERROR, result.getStatus());
283 assertEquals("APP_ID_NOT_FOUND;\tApplication ID not found in request;\t[]", result.getMessage());
284 assertNull(result.getUser());
285 }
286
287 public void testBadProtocolVersion() throws Exception
288 {
289 EncryptedCertificate cert = new EncryptedCertificate()
290 {
291 public String getCertificate()
292 {
293 return "cert";
294 };
295
296 public String getID()
297 {
298 return "me-id";
299 }
300
301 public String getMagicNumber()
302 {
303 return "majick";
304 }
305
306 public Integer getProtocolVersion()
307 {
308 return new Integer(1);
309 }
310
311 public String getSecretKey()
312 {
313 return "dis-is-a-sekrit";
314 }
315 };
316 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
317 request.addHeader(TrustedApplicationUtils.Header.Request.VERSION, "a-dodgy-version");
318
319 Authenticator.Result result = authenticator.authenticate(request, new MockResponse());
320
321 assertNotNull(result);
322 assertEquals(Authenticator.Result.Status.ERROR, result.getStatus());
323 assertEquals("BAD_PROTOCOL_VERSION;\tBad protocol version: {0};\t[\"a-dodgy-version\"]", result.getMessage());
324 assertNull(result.getUser());
325 }
326
327 public void testMissingSecretKey() throws Exception
328 {
329 EncryptedCertificate cert = new EncryptedCertificate()
330 {
331 public String getCertificate()
332 {
333 return "cert";
334 };
335
336 public String getID()
337 {
338 return "me-id";
339 }
340
341 public String getMagicNumber()
342 {
343 return "majick";
344 }
345
346 public Integer getProtocolVersion()
347 {
348 return new Integer(1);
349 }
350
351 public String getSecretKey()
352 {
353 return "";
354 }
355 };
356 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
357
358 Authenticator.Result result = authenticator.authenticate(request, new MockResponse());
359
360 assertNotNull(result);
361 assertEquals(Authenticator.Result.Status.ERROR, result.getStatus());
362 assertEquals("SECRET_KEY_NOT_FOUND;\tSecret Key not found in request;\t[]", result.getMessage());
363 assertNull(result.getUser());
364 }
365
366 public void testMissingMagicNumber() throws Exception
367 {
368 EncryptedCertificate cert = new EncryptedCertificate()
369 {
370 public String getCertificate()
371 {
372 return "cert";
373 };
374
375 public String getID()
376 {
377 return "me-id";
378 }
379
380 public String getMagicNumber()
381 {
382 return null;
383 }
384
385 public Integer getProtocolVersion()
386 {
387 return new Integer(1);
388 }
389
390 public String getSecretKey()
391 {
392 return "asudyasduh";
393 }
394 };
395 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
396
397 Authenticator.Result result = authenticator.authenticate(request, new MockResponse());
398
399 assertNotNull(result);
400 assertEquals(Authenticator.Result.Status.ERROR, result.getStatus());
401 assertEquals("MAGIC_NUMBER_NOT_FOUND;\tMagic Number not found in request;\t[]", result.getMessage());
402 assertNull(result.getUser());
403 }
404
405 public void testBadCertificate() throws Exception
406 {
407 CurrentApplication me = manager.getCurrentApplication();
408 EncryptedCertificate cert = me.encode(USER);
409 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
410 request.addHeader(TrustedApplicationUtils.Header.Request.CERTIFICATE, "bad-cert");
411
412 Authenticator.Result result = authenticator.authenticate(request, new MockResponse());
413
414 assertNotNull(result);
415 assertEquals(result.getMessage(), Authenticator.Result.Status.ERROR, result.getStatus());
416 assertEquals("SYSTEM;\tException: {0} occurred serving request for application: {1};\t[\"java.lang.NullPointerException: what a bad certificate!\",\"bad-cert\"]", result.getMessage());
417 assertNull(result.getUser());
418 }
419
420 public void testPrincipalNotFound() throws Exception
421 {
422 CurrentApplication me = manager.getCurrentApplication();
423 EncryptedCertificate cert = me.encode("unknown-principal");
424 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
425
426 Authenticator.Result result = authenticator.authenticate(request, new MockResponse());
427
428 assertNotNull(result);
429 assertEquals(result.getMessage(), Authenticator.Result.Status.FAILED, result.getStatus());
430 assertEquals("USER_UNKNOWN;\tUnknown User: {0};\t[\"unknown-principal\"]", result.getMessage());
431 assertNull(result.getUser());
432 }
433
434 public void testPrincipalLoginDenied() throws Exception
435 {
436 CurrentApplication me = manager.getCurrentApplication();
437 EncryptedCertificate cert = me.encode(USER);
438 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
439
440 canLogin[0] = false;
441 Authenticator.Result result = authenticator.authenticate(request, new MockResponse());
442
443 assertNotNull(result);
444 assertEquals(result.getMessage(), Authenticator.Result.Status.FAILED, result.getStatus());
445 assertEquals("PERMISSION_DENIED;\tPermission Denied;\t[]", result.getMessage());
446 assertNull(result.getUser());
447 }
448
449 public void testBadRequestIp() throws Exception
450 {
451 CurrentApplication me = manager.getCurrentApplication();
452 EncryptedCertificate cert = me.encode(USER);
453 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
454 request.addHeader("ip-mismatch", "true");
455
456 Authenticator.Result result = authenticator.authenticate(request, new MockResponse());
457
458 assertNotNull(result);
459 assertEquals(result.getMessage(), Authenticator.Result.Status.ERROR, result.getStatus());
460 assertEquals("BAD_REMOTE_IP;\tRequest not allowed from IP address: {0};\t[\"i.am.a.teapot\"]", result.getMessage());
461 assertNull(result.getUser());
462 }
463
464 public void testBadXForwardIp() throws Exception
465 {
466 CurrentApplication me = manager.getCurrentApplication();
467 EncryptedCertificate cert = me.encode(USER);
468 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
469 request.addHeader("forward-mismatch", "true");
470
471 Authenticator.Result result = authenticator.authenticate(request, new MockResponse());
472
473 assertNotNull(result);
474 assertEquals(Authenticator.Result.Status.ERROR, result.getStatus());
475 assertEquals("BAD_XFORWARD_IP;\tRequest not allowed from IP address: {0};\t[\"i.am.a.teapot\"]", result.getMessage());
476 assertNull(result.getUser());
477 }
478
479 public void testBadRequestUrl() throws Exception
480 {
481 CurrentApplication me = manager.getCurrentApplication();
482 EncryptedCertificate cert = me.encode(USER);
483 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1("/jira/secure/DeleteProject.jspa", cert);
484 request.addHeader("url-mismatch", "true");
485
486 Authenticator.Result result = authenticator.authenticate(request, new MockResponse());
487
488 assertNotNull(result);
489 assertEquals(Authenticator.Result.Status.ERROR, result.getStatus());
490 assertEquals("BAD_URL;\tRequest not allowed to access URL: {0};\t[\"/jira/secure/DeleteProject.jspa\"]", result.getMessage());
491 assertNull(result.getUser());
492 }
493 }