1 package com.atlassian.security.auth.trustedapps.filter;
2
3 import com.atlassian.security.auth.trustedapps.ApplicationCertificate;
4 import com.atlassian.security.auth.trustedapps.DefaultEncryptedCertificate;
5 import com.atlassian.security.auth.trustedapps.InvalidCertificateException;
6 import com.atlassian.security.auth.trustedapps.TransportErrorMessage;
7 import com.atlassian.security.auth.trustedapps.TrustedApplication;
8 import com.atlassian.security.auth.trustedapps.TrustedApplicationUtils;
9 import com.atlassian.security.auth.trustedapps.TrustedApplicationsManager;
10 import com.atlassian.security.auth.trustedapps.UserResolver;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13
14 import javax.servlet.http.HttpServletRequest;
15 import javax.servlet.http.HttpServletResponse;
16 import java.security.Principal;
17
18
19
20
21 public class TrustedApplicationFilterAuthenticator implements Authenticator
22 {
23 private static final Logger log = LoggerFactory.getLogger(TrustedApplicationFilterAuthenticator.class);
24
25 final TrustedApplicationsManager appManager;
26 final UserResolver resolver;
27 final AuthenticationController authenticationController;
28
29 public TrustedApplicationFilterAuthenticator(TrustedApplicationsManager appManager, UserResolver resolver, AuthenticationController authenticationController)
30 {
31 this.appManager = appManager;
32 this.resolver = resolver;
33 this.authenticationController = authenticationController;
34 }
35
36 public Result authenticate(HttpServletRequest request, HttpServletResponse response)
37 {
38 final String certStr = request.getHeader(TrustedApplicationUtils.Header.Request.CERTIFICATE);
39 if (isBlank(certStr))
40 {
41 return new Result.NoAttempt();
42 }
43
44 final String id = request.getHeader(TrustedApplicationUtils.Header.Request.ID);
45 if (isBlank(id))
46 {
47 final Result.Error result = new Result.Error(new TransportErrorMessage.ApplicationIdNotFoundInRequest());
48 setFailureHeader(response, result.getMessage());
49 return result;
50 }
51
52 final String key = request.getHeader(TrustedApplicationUtils.Header.Request.SECRET_KEY);
53 if (isBlank(key))
54 {
55 final Result.Error result = new Result.Error(new TransportErrorMessage.SecretKeyNotFoundInRequest());
56 setFailureHeader(response, result.getMessage());
57 return result;
58 }
59
60 final String magicNumber = request.getHeader(TrustedApplicationUtils.Header.Request.MAGIC);
61
62 final String version = request.getHeader(TrustedApplicationUtils.Header.Request.VERSION);
63 final Integer protocolVersion;
64 try
65 {
66 protocolVersion = (!isBlank(version)) ? new Integer(version) : null;
67 }
68 catch (NumberFormatException e)
69 {
70 final Result.Error result = new Result.Error(new TransportErrorMessage.BadProtocolVersion(version));
71 setFailureHeader(response, result.getMessage());
72 return result;
73 }
74
75
76 if (protocolVersion != null)
77 {
78 if (isBlank(magicNumber))
79 {
80 final Result.Error result = new Result.Error(new TransportErrorMessage.MagicNumberNotFoundInRequest());
81 setFailureHeader(response, result.getMessage());
82 return result;
83 }
84 }
85
86 TrustedApplication app = appManager.getTrustedApplication(id);
87 if (app == null)
88 {
89 final Result.Failure result = new Result.Failure(new TransportErrorMessage.ApplicationUnknown(id));
90 setFailureHeader(response, result.getMessage());
91 return result;
92 }
93
94 final ApplicationCertificate certificate;
95 try
96 {
97 certificate = app.decode(new DefaultEncryptedCertificate(id, key, certStr, protocolVersion, magicNumber), request);
98 }
99 catch (InvalidCertificateException ex)
100 {
101 log.warn("Failed to login trusted application: " + app.getID() + " due to: " + ex);
102
103 log.debug("Failed to login trusted application cause", ex);
104 final Result.Error result = new Result.Error(ex.getTransportErrorMessage());
105 setFailureHeader(response, result.getMessage());
106 return result;
107 }
108 final Principal user = resolver.resolve(certificate);
109 if (user == null)
110 {
111 log.warn("User '" + certificate.getUserName() + "' referenced by trusted application: '" + app.getID() + "' is not found.");
112 final Result.Failure result = new Result.Failure(new TransportErrorMessage.UserUnknown(certificate.getUserName()));
113 setFailureHeader(response, result.getMessage());
114 return result;
115 }
116 else if (!authenticationController.canLogin(user, request))
117 {
118
119 log.warn("User '" + certificate.getUserName() + "' referenced by trusted application: '" + app.getID() + "' cannot login.");
120 final Result.Failure result = new Result.Failure(new TransportErrorMessage.PermissionDenied());
121 setFailureHeader(response, result.getMessage());
122 return result;
123 }
124
125 return new Result.Success(user);
126 }
127
128 private static void setFailureHeader(HttpServletResponse response, String message)
129 {
130 response.setHeader(TrustedApplicationUtils.Header.Response.STATUS, TrustedApplicationsFilter.Status.ERROR);
131 response.addHeader(TrustedApplicationUtils.Header.Response.ERROR, message);
132 if (log.isInfoEnabled())
133 {
134 log.info(message, new RuntimeException(message));
135 }
136 }
137
138 private static boolean isBlank(String input)
139 {
140 return (input == null) || input.trim().length() == 0;
141 }
142 }