1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.security.jaspi;
20
21 import java.io.IOException;
22 import java.security.Principal;
23 import java.util.Map;
24 import java.util.Set;
25
26 import javax.security.auth.Subject;
27 import javax.security.auth.message.AuthException;
28 import javax.security.auth.message.AuthStatus;
29 import javax.security.auth.message.callback.CallerPrincipalCallback;
30 import javax.security.auth.message.callback.GroupPrincipalCallback;
31 import javax.security.auth.message.config.ServerAuthConfig;
32 import javax.security.auth.message.config.ServerAuthContext;
33 import javax.servlet.ServletRequest;
34 import javax.servlet.ServletResponse;
35 import javax.servlet.http.HttpServletRequest;
36 import javax.servlet.http.HttpServletResponse;
37 import javax.servlet.http.HttpSession;
38
39 import org.eclipse.jetty.security.IdentityService;
40 import org.eclipse.jetty.security.ServerAuthException;
41 import org.eclipse.jetty.security.UserAuthentication;
42 import org.eclipse.jetty.security.authentication.DeferredAuthentication;
43 import org.eclipse.jetty.security.authentication.LoginAuthenticator;
44 import org.eclipse.jetty.security.authentication.SessionAuthentication;
45 import org.eclipse.jetty.server.Authentication;
46 import org.eclipse.jetty.server.Authentication.User;
47 import org.eclipse.jetty.server.UserIdentity;
48 import org.eclipse.jetty.util.log.Log;
49 import org.eclipse.jetty.util.log.Logger;
50
51
52
53
54 public class JaspiAuthenticator extends LoginAuthenticator
55 {
56 private static final Logger LOG = Log.getLogger(JaspiAuthenticator.class.getName());
57
58 private final ServerAuthConfig _authConfig;
59
60 private final Map _authProperties;
61
62 private final ServletCallbackHandler _callbackHandler;
63
64 private final Subject _serviceSubject;
65
66 private final boolean _allowLazyAuthentication;
67
68 private final IdentityService _identityService;
69
70
71
72 public JaspiAuthenticator(ServerAuthConfig authConfig, Map authProperties, ServletCallbackHandler callbackHandler, Subject serviceSubject,
73 boolean allowLazyAuthentication, IdentityService identityService)
74 {
75
76 if (callbackHandler == null) throw new NullPointerException("No CallbackHandler");
77 if (authConfig == null) throw new NullPointerException("No AuthConfig");
78 this._authConfig = authConfig;
79 this._authProperties = authProperties;
80 this._callbackHandler = callbackHandler;
81 this._serviceSubject = serviceSubject;
82 this._allowLazyAuthentication = allowLazyAuthentication;
83 this._identityService = identityService;
84 }
85
86 public void setConfiguration(AuthConfiguration configuration)
87 {
88 super.setConfiguration(configuration);
89 }
90
91 public String getAuthMethod()
92 {
93 return "JASPI";
94 }
95
96 public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException
97 {
98 JaspiMessageInfo info = new JaspiMessageInfo(request, response, mandatory);
99 request.setAttribute("org.eclipse.jetty.security.jaspi.info", info);
100
101 Authentication a = validateRequest(info);
102
103
104 if (_allowLazyAuthentication && !info.isAuthMandatory() && a == Authentication.UNAUTHENTICATED)
105 a = new DeferredAuthentication(this);
106 return a;
107 }
108
109
110 public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
111 {
112 JaspiMessageInfo info = (JaspiMessageInfo) req.getAttribute("org.eclipse.jetty.security.jaspi.info");
113 if (info == null) throw new NullPointerException("MessageInfo from request missing: " + req);
114 return secureResponse(info, validatedUser);
115 }
116
117
118
119
120
121 @Override
122 public UserIdentity login(String username, Object password, ServletRequest request)
123 {
124 UserIdentity user = _loginService.login(username, password, request);
125 if (user != null)
126 {
127 renewSession((HttpServletRequest)request, null);
128 HttpSession session = ((HttpServletRequest)request).getSession(true);
129 if (session != null)
130 {
131 SessionAuthentication sessionAuth = new SessionAuthentication(getAuthMethod(), user, password);
132 session.setAttribute(SessionAuthentication.__J_AUTHENTICATED, sessionAuth);
133 }
134 }
135 return user;
136 }
137
138
139
140 public Authentication validateRequest(JaspiMessageInfo messageInfo) throws ServerAuthException
141 {
142 try
143 {
144 String authContextId = _authConfig.getAuthContextID(messageInfo);
145 ServerAuthContext authContext = _authConfig.getAuthContext(authContextId, _serviceSubject, _authProperties);
146 Subject clientSubject = new Subject();
147
148 AuthStatus authStatus = authContext.validateRequest(messageInfo, clientSubject, _serviceSubject);
149
150 if (authStatus == AuthStatus.SEND_CONTINUE) return Authentication.SEND_CONTINUE;
151 if (authStatus == AuthStatus.SEND_FAILURE) return Authentication.SEND_FAILURE;
152
153 if (authStatus == AuthStatus.SUCCESS)
154 {
155 Set<UserIdentity> ids = clientSubject.getPrivateCredentials(UserIdentity.class);
156 UserIdentity userIdentity;
157 if (ids.size() > 0)
158 {
159 userIdentity = ids.iterator().next();
160 }
161 else
162 {
163 CallerPrincipalCallback principalCallback = _callbackHandler.getThreadCallerPrincipalCallback();
164 if (principalCallback == null) { return Authentication.UNAUTHENTICATED; }
165 Principal principal = principalCallback.getPrincipal();
166 if (principal == null)
167 {
168 String principalName = principalCallback.getName();
169 Set<Principal> principals = principalCallback.getSubject().getPrincipals();
170 for (Principal p : principals)
171 {
172 if (p.getName().equals(principalName))
173 {
174 principal = p;
175 break;
176 }
177 }
178 if (principal == null) { return Authentication.UNAUTHENTICATED; }
179 }
180 GroupPrincipalCallback groupPrincipalCallback = _callbackHandler.getThreadGroupPrincipalCallback();
181 String[] groups = groupPrincipalCallback == null ? null : groupPrincipalCallback.getGroups();
182 userIdentity = _identityService.newUserIdentity(clientSubject, principal, groups);
183 }
184
185 HttpSession session = ((HttpServletRequest)messageInfo.getRequestMessage()).getSession(false);
186 Authentication cached = (session == null?null:(SessionAuthentication)session.getAttribute(SessionAuthentication.__J_AUTHENTICATED));
187 if (cached != null)
188 return cached;
189
190 return new UserAuthentication(getAuthMethod(), userIdentity);
191 }
192 if (authStatus == AuthStatus.SEND_SUCCESS)
193 {
194
195 return Authentication.SEND_SUCCESS;
196 }
197 if (authStatus == AuthStatus.FAILURE)
198 {
199 HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
200 response.sendError(HttpServletResponse.SC_FORBIDDEN);
201 return Authentication.SEND_FAILURE;
202 }
203
204 throw new IllegalStateException("No AuthStatus returned");
205 }
206 catch (IOException|AuthException e)
207 {
208 throw new ServerAuthException(e);
209 }
210 }
211
212 public boolean secureResponse(JaspiMessageInfo messageInfo, Authentication validatedUser) throws ServerAuthException
213 {
214 try
215 {
216 String authContextId = _authConfig.getAuthContextID(messageInfo);
217 ServerAuthContext authContext = _authConfig.getAuthContext(authContextId, _serviceSubject, _authProperties);
218
219
220 AuthStatus status = authContext.secureResponse(messageInfo, _serviceSubject);
221 return (AuthStatus.SEND_SUCCESS.equals(status));
222 }
223 catch (AuthException e)
224 {
225 throw new ServerAuthException(e);
226 }
227 }
228
229 }