--- /dev/null
+/*
+ * Copyright [2006] [University Corporation for Advanced Internet Development, Inc.]
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.internet2.middleware.shibboleth.idp.authn;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.apache.log4j.Logger;
+import org.joda.time.DateTime;
+import org.opensaml.xml.util.Pair;
+
+import edu.internet2.middleware.shibboleth.common.profile.ProfileHandlerManager;
+import edu.internet2.middleware.shibboleth.common.session.SessionManager;
+import edu.internet2.middleware.shibboleth.idp.session.AuthenticationMethodInformation;
+import edu.internet2.middleware.shibboleth.idp.session.ServiceInformation;
+import edu.internet2.middleware.shibboleth.idp.session.Session;
+import edu.internet2.middleware.shibboleth.idp.session.impl.AuthenticationMethodInformationImpl;
+import edu.internet2.middleware.shibboleth.idp.session.impl.ServiceInformationImpl;
+
+/**
+ * Manager responsible for handling authentication requests.
+ */
+public class AuthenticationEngine extends HttpServlet {
+
+ /** Class logger. */
+ private static final Logger log = Logger.getLogger(AuthenticationEngine.class);
+
+ /**
+ * Gets the manager used to retrieve handlers for requests.
+ *
+ * @return manager used to retrieve handlers for requests
+ */
+ public ProfileHandlerManager getProfileHandlerManager() {
+ return (ProfileHandlerManager) getServletContext().getAttribute("handlerManager");
+ }
+
+ /**
+ * Gets the session manager to be used.
+ *
+ * @return session manager to be used
+ */
+ @SuppressWarnings("unchecked")
+ public SessionManager<Session> getSessionManager() {
+ return (SessionManager<Session>) getServletContext().getAttribute("sessionManager");
+ }
+
+ /**
+ * Gets the authentication handler manager used by this engine.
+ *
+ * @return authentication handler manager used by this engine
+ */
+ public AuthenticationHandlerManager getAuthenticationHandlerManager() {
+ return (AuthenticationHandlerManager) getServletContext().getAttribute("authenticationHandlerManager");
+ }
+
+
+ /**
+ * Returns control back to the authentication engine.
+ *
+ * @param httpRequest current http request
+ * @param httpResponse current http response
+ * @param loginContext user login context
+ */
+ public static void returnToAuthenticationEngine(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
+ HttpSession httpSession = httpRequest.getSession();
+
+ LoginContext loginContext = (LoginContext) httpSession.getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
+
+ try {
+ RequestDispatcher distpather = httpRequest.getRequestDispatcher(loginContext.getAuthenticationManagerURL());
+ distpather.forward(httpRequest, httpResponse);
+ } catch (IOException e) {
+ log.fatal("Unable to return control back to authentication engine", e);
+ } catch (ServletException e) {
+ log.fatal("Unable to return control back to authentication engine", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException,
+ IOException {
+ HttpSession httpSession = httpRequest.getSession();
+
+ LoginContext loginContext = (LoginContext) httpSession.getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
+ if (loginContext == null) {
+ // TODO error
+ }
+
+ // If authentication has been attempted, don't try it again.
+ if (loginContext.getAuthenticationAttempted()) {
+ handleNewAuthnRequest(loginContext, httpRequest, httpResponse);
+ } else {
+ finishAuthnRequest(loginContext, httpRequest, httpResponse);
+ }
+ }
+
+ /**
+ * Handle a new authentication request.
+ *
+ * @param loginContext The {@link LoginContext} for the new authentication request
+ * @param httpRequest The servlet request containing the authn request
+ * @param httpResponse The associated servlet response.
+ *
+ * @throws IOException thrown if there is a problem reading/writting to the HTTP request/response
+ * @throws ServletException thrown if there is a problem transferring control to the authentication handler
+ */
+ protected void handleNewAuthnRequest(LoginContext loginContext, HttpServletRequest httpRequest,
+ HttpServletResponse httpResponse) throws ServletException, IOException {
+
+ HttpSession httpSession = httpRequest.getSession();
+ String shibSessionId = (String) httpSession.getAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE);
+ Session shibSession = getSessionManager().getSession(shibSessionId);
+
+ AuthenticationMethodInformation authenticationMethod = getUsableExistingAuthenticationMethod(loginContext,
+ shibSession);
+ if (authenticationMethod != null) {
+ loginContext.setAuthenticationDuration(authenticationMethod.getAuthenticationDuration());
+ loginContext.setAuthenticationInstant(authenticationMethod.getAuthenticationInstant());
+ loginContext.setAuthenticationMethod(authenticationMethod.getAuthenticationMethod());
+ loginContext.setPrincipalAuthenticated(true);
+ loginContext.setPrincipalName(shibSession.getPrincipalName());
+ finishAuthnRequest(loginContext, httpRequest, httpResponse);
+ } else {
+ Pair<String, AuthenticationHandler> handler = getAuthenticationHandlerManager().getAuthenticationHandler(
+ loginContext);
+
+ if (handler == null) {
+ loginContext.setPassiveAuth(false);
+ loginContext
+ .setAuthenticationFailureMessage("No installed AuthenticationHandler can satisfy the authentication request.");
+ log.error("No installed AuthenticationHandler can satisfy the authentication request.");
+ finishAuthnRequest(loginContext, httpRequest, httpResponse);
+ }
+
+ loginContext.setAuthenticationAttempted();
+ loginContext.setAuthenticationDuration(handler.getSecond().getAuthenticationDuration());
+ loginContext.setAuthenticationMethod(handler.getFirst());
+ loginContext.setAuthenticationManagerURL(httpRequest.getRequestURI());
+
+ httpSession.setAttribute(LoginContext.LOGIN_CONTEXT_KEY, loginContext);
+ handler.getSecond().login(loginContext, httpRequest, httpResponse);
+ }
+ }
+
+ /**
+ * Gets the authentication method, currently active for the user, that also meets the requirements expressed by the
+ * login context. If a method is returned the user does not need to authenticate again, if null is returned then the
+ * user must be authenticated.
+ *
+ * @param loginContext user login context
+ * @param shibSession user's shibboleth session
+ *
+ * @return active authentication method that meets authentication requirements or null
+ */
+ protected AuthenticationMethodInformation getUsableExistingAuthenticationMethod(LoginContext loginContext,
+ Session shibSession) {
+ if (loginContext.getForceAuth() || shibSession == null) {
+ return null;
+ }
+
+ List<String> preferredAuthnMethods = loginContext.getRequestedAuthenticationMethods();
+
+ if (preferredAuthnMethods == null || preferredAuthnMethods.size() == 0) {
+ for (AuthenticationMethodInformation authnMethod : shibSession.getAuthenticationMethods().values()) {
+ if (!authnMethod.isExpired()) {
+ return authnMethod;
+ }
+ }
+ } else {
+ for (String preferredAuthnMethod : preferredAuthnMethods) {
+ if (shibSession.getAuthenticationMethods().containsKey(preferredAuthnMethod)) {
+ AuthenticationMethodInformation authnMethodInfo = shibSession.getAuthenticationMethods().get(
+ preferredAuthnMethod);
+ if (!authnMethodInfo.isExpired()) {
+ return authnMethodInfo;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Handle the "return leg" of an authentication request (i.e. clean up after an authentication handler has run).
+ *
+ * @param loginContext The {@link LoginContext} for the new authentication request
+ * @param httpRequest The servlet request containing the authn request
+ * @param httpResponse The associated servlet response.
+ *
+ * @throws IOException thrown if there is a problem reading/writting to the HTTP request/response
+ * @throws ServletException thrown if there is a problem transferring control to the authentication profile handler
+ */
+ protected void finishAuthnRequest(LoginContext loginContext, HttpServletRequest httpRequest,
+ HttpServletResponse httpResponse) throws ServletException, IOException {
+
+ HttpSession httpSession = httpRequest.getSession();
+ String shibSessionId = (String) httpSession.getAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE);
+ Session shibSession = null;
+ AuthenticationMethodInformation authnMethodInfo = null;
+ ServiceInformation serviceInfo = null;
+
+ if (!loginContext.getAuthenticationAttempted()) {
+ // Authentication wasn't attempted so we're using a previously established authentication method
+ shibSession = getSessionManager().getSession(shibSessionId);
+ authnMethodInfo = shibSession.getAuthenticationMethods().get(loginContext.getAuthenticationMethod());
+ } else {
+ if (shibSessionId == null) {
+ InetAddress addr;
+ try {
+ addr = InetAddress.getByName(httpRequest.getRemoteAddr());
+ } catch (UnknownHostException ex) {
+ addr = null;
+ }
+
+ shibSession = (Session) getSessionManager().createSession(addr, loginContext.getPrincipalName());
+ httpSession.setAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE, shibSession.getSessionID());
+
+ authnMethodInfo = new AuthenticationMethodInformationImpl(loginContext.getAuthenticationMethod(),
+ new DateTime(), loginContext.getAuthenticationDuration());
+ shibSession.getAuthenticationMethods().put(authnMethodInfo.getAuthenticationMethod(), authnMethodInfo);
+ }
+ }
+
+ loginContext.setSessionID(shibSession.getSessionID());
+ shibSession.setLastActivityInstant(new DateTime());
+
+ serviceInfo = shibSession.getServicesInformation().get(loginContext.getRelyingPartyId());
+ if (serviceInfo == null) {
+ serviceInfo = new ServiceInformationImpl(loginContext.getRelyingPartyId(), new DateTime(), authnMethodInfo);
+ }
+
+ RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(loginContext.getProfileHandlerURL());
+ dispatcher.forward(httpRequest, httpResponse);
+ }
+
+ // TODO logout support
+}
\ No newline at end of file
import javax.servlet.http.HttpServletResponse;
/**
- * Authentication handlers are responsible for authenticating a user using a
- * particular authentication context class and logging users out for that same
- * mechanism.
+ * Authentication handlers are responsible for authenticating a user using a particular authentication context class and
+ * logging users out for that same mechanism.
*
- * When this handler is invoked to log a user in the incoming request will
- * contain a {@link AuthnRequest} attribute registered under the name
- * <strong>AuthnRequest</strong>. If the authentication request coming into the
- * IdP is not a SAML 2 request the receiving profile handler will translate the
- * incoming details into a {@link AuthnRequest}.
+ * When this handler is invoked to log a user in the incoming request will contain a {@link AuthnRequest} attribute
+ * registered under the name <strong>AuthnRequest</strong>. If the authentication request coming into the IdP is not a
+ * SAML 2 request the receiving profile handler will translate the incoming details into a {@link AuthnRequest}.
*
- * Upon successfull authentication the handler <strong>must</strong> set a
- * request attribute called <strong>principal</strong> with the principal name
- * of the authenticated user. It must then forward the request/response to the
- * provided return location by means of the
- * {@link javax.servlet.RequestDispatcher.RequestDispatcher#forward(
+ * Upon successfull authentication the handler <strong>must</strong> set a request attribute called <strong>principal</strong>
+ * with the principal name of the authenticated user. It must then forward the request/response to the provided return
+ * location by means of the {@link javax.servlet.RequestDispatcher.RequestDispatcher#forward(
* javax.servlet.ServletRequest, javax.servlet.ServletResponse)} method.
*
- * When this handler is invoked to log a user out of the particular
- * authentication source the handler may perform any operation necessary to log
- * a user out. When finished it must then forward the request/response to the
- * provided return location by means of the
- * {@link RequestDispatcher#forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse)}
- * method. This call will occur before SAML logout requests have been sent to
- * all services supporting such requests.
+ * When this handler is invoked to log a user out of the particular authentication source the handler may perform any
+ * operation necessary to log a user out. When finished it must then forward the request/response to the provided return
+ * location by means of the
+ * {@link RequestDispatcher#forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse)} method. This call will
+ * occur before SAML logout requests have been sent to all services supporting such requests.
*
- * AuthentcationHandlers <strong>MUST NOT</strong> change or add any data to
- * the user's {@link javax.servlet.http.HttpSession} that persists past the
- * process of authenticating the user, that is no additional session data may be
- * added and no existing session data may be changed when the handler redirects
- * back to the return location.
+ * AuthentcationHandlers <strong>MUST NOT</strong> change or add any data to the user's
+ * {@link javax.servlet.http.HttpSession} that persists past the process of authenticating the user, that is no
+ * additional session data may be added and no existing session data may be changed when the handler redirects back to
+ * the return location.
*/
public interface AuthenticationHandler {
+
+ /** Request attribute to which user's principal name should be bound. */
+ public static final String PRINCIPAL_NAME_KEY = "principal";
- /**
- * Authenticates the user making the request.
- *
- * @param request
- * user request
- * @param response
- * response to user
- * @param loginCtx
- * The {@link LoginContext} for the reqeust.
- */
- public void login(HttpServletRequest request, HttpServletResponse response,
- LoginContext loginCtx);
+ /**
+ * Gets the length of time, in milliseconds, after which a user authenticated by this handler should be
+ * re-authenticated.
+ *
+ * @return length of time, in milliseconds, after which a user should be re-authenticated
+ */
+ public long getAuthenticationDuration();
+
+ /**
+ * Gets whether this handler supports passive authentication.
+ *
+ * @return whether this handler supports passive authentication
+ */
+ public boolean supportsPassive();
- /**
- * Logs out the given user from the authentication mechanism represented by
- * this handler.
- *
- * @param request
- * user request
- * @param response
- * response to user
- * @param principal
- * principal named as returned during authentication
- */
- public void logout(HttpServletRequest request,
- HttpServletResponse response, String principal);
+ /**
+ * Returns if this handler supports the ability to force a user to (re-)authenticate.
+ *
+ * @return if this handler can force a user to (re-)authenticate.
+ */
+ public boolean supportsForceAuthentication();
- /**
- * Gets whether this handler supports passive authentication.
- *
- * @return whether this handler supports passive authentication
- */
- public boolean supportsPassive();
+ /**
+ * Authenticates the user making the request.
+ * @param loginContext The {@link LoginContext} for the reqeust.
+ * @param httpRequest user request
+ * @param httpResponse response to user
+ */
+ public void login(LoginContext loginContext, HttpServletRequest httpRequest, HttpServletResponse httpResponse);
- /**
- * Returns if this handler supports the ability to force a user to
- * (re-)authenticate.
- *
- * @return if this handler can force a user to (re-)authenticate.
- */
- public boolean supportsForceAuthentication();
+ /**
+ * Logs out the given user from the authentication mechanism represented by this handler.
+ *
+ * @param request user request
+ * @param response response to user
+ * @param principal principal named as returned during authentication
+ */
+ public void logout(HttpServletRequest request, HttpServletResponse response, String principal);
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright [2007] [University Corporation for Advanced Internet Development, Inc.]
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.internet2.middleware.shibboleth.idp.authn;
+
+import java.util.Map;
+
+import org.opensaml.xml.util.Pair;
+
+/**
+ * Manager for registering and retrieving authentication handlers.
+ */
+public interface AuthenticationHandlerManager {
+
+ /**
+ * Gets the registered authentication handlers.
+ *
+ * @return registered authentication handlers
+ */
+ public Map<String, AuthenticationHandler> getAuthenticationHandlers();
+
+ /**
+ * Gets the authentication handler appropriate for the given loging context. The mechanism used to determine the
+ * "appropriate" handler is implementation specific.
+ *
+ * @param loginContext current login context
+ *
+ * @return authentication method URI and handler appropriate for given login context
+ */
+ public Pair<String, AuthenticationHandler> getAuthenticationHandler(LoginContext loginContext);
+}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright [2006] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package edu.internet2.middleware.shibboleth.idp.authn;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-import javolution.util.FastMap;
-
-import org.apache.log4j.Logger;
-
-import edu.internet2.middleware.shibboleth.common.session.SessionManager;
-import edu.internet2.middleware.shibboleth.idp.session.AuthenticationMethodInformation;
-import edu.internet2.middleware.shibboleth.idp.session.Session;
-import edu.internet2.middleware.shibboleth.idp.session.impl.AuthenticationMethodInformationImpl;
-
-/**
- * Manager responsible for handling authentication requests.
- */
-//TODO map needed objects into servlet context information and fetch from there
-public class AuthenticationManager extends HttpServlet {
-
- /** log4j. */
- private final Logger log = Logger.getLogger(AuthenticationManager.class);
-
- /** SessionManager to be used. */
- private SessionManager sessionMgr;
-
- /** Map of URIs onto AuthenticationHandlerInfo. */
- private Map<String, AuthenticationHandler> handlerMap = new ConcurrentHashMap<String, AuthenticationHandler>();
-
- /** The default AuthenticationHandler. */
- private AuthenticationHandler defaultHandler;
-
- /** The URI for the default AuthenticationHandler. */
- private String defaultHandlerURI;
-
- /**
- * Gets the session manager to be used.
- *
- * @return session manager to be used
- */
- public SessionManager getSessionManager() {
- return sessionMgr;
- }
-
- /**
- * Sets the session manager to be used.
- *
- * @param manager session manager to be used.
- */
- public void setSessionManager(final SessionManager manager) {
- sessionMgr = manager;
- }
-
- /**
- * Get the map of {@link AuthenticationHandlers}.
- *
- * @return The map of AuthenticationHandlers
- */
- public Map<String, AuthenticationHandler> getHandlerMap() {
-
- return new FastMap<String, AuthenticationHandler>(handlerMap);
- }
-
- /**
- * Set the {@link AuthenticationHandler} map.
- *
- * @param handlerMap The Map of URIs to AuthenticationHandlers
- */
- public void setHandlerMap(final Map<String, AuthenticationHandler> handlerMap) {
-
- for (String uri : handlerMap.keySet()) {
- addHandlerMapping(uri, handlerMap.get(uri));
- }
- }
-
- /**
- * Add a <code><String:AuthenticationHandler&gr;</code> mapping to the AuthenticationManager's table. If a
- * mapping for the URI already exists, it will be overwritten.
- *
- * The URI SHOULD be from the saml-autn-context-2.0-os
- *
- * @param uri A URI identifying the authentcation method.
- * @param handler The AuthenticationHandler.
- */
- public void addHandlerMapping(String uri, AuthenticationHandler handler) {
-
- if (uri == null || handler == null) {
- return;
- }
-
- log.debug("AuthenticationManager: Registering " + handler.getClass().getName() + " for " + uri);
-
- handlerMap.put(uri, handler);
- }
-
- /**
- * Register the default {@link AuthenticationHandler}.
- *
- * @param uri The URI of the default authentication handler (from saml-authn-context-2.0-os)
- * @param handler The default {@link AuthenticationHandler}.
- */
- public void setDefaultHandler(String uri, AuthenticationHandler handler) {
-
- log.debug("AuthenticationManager: Registering default handler " + handler.getClass().getName());
-
- defaultHandler = handler;
- defaultHandlerURI = uri;
- }
-
- /**
- * Remove a <String:AuthenticationHandler> mapping from the AuthenticationManager's table.
- *
- * The URI SHOULD be from the saml-authn-context-2.0-os
- *
- * @param uri A URI identifying the authentcation method.
- */
- public void removeHandlerMapping(String uri) {
-
- if (uri == null) {
- return;
- }
-
- log.debug("AuthenticationManager: Unregistering handler for " + uri);
-
- handlerMap.remove(uri);
- }
-
- /**
- * Primary entrypoint for the AuthnManager.
- *
- * @param req The ServletRequest.
- * @param resp The ServletResponse.
- */
- public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-
- if (req == null || resp == null) {
- log.error("AuthenticationManager: Invalid parameters in AuthenticationManager's doPost().");
- return;
- }
-
- HttpSession httpSession = req.getSession();
- Object o = httpSession.getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
-
- if (o == null || !(o instanceof LoginContext)) {
- log.error("AuthenticationManager: Invalid login context object found in HttpSession.");
- return;
- }
- LoginContext loginContext = (LoginContext) o;
-
- // If authentication has been attempted, don't try it again.
- if (loginContext.getAuthenticationAttempted()) {
- handleNewAuthnRequest(loginContext, req, resp);
- } else {
- finishAuthnRequest(loginContext, req, resp);
- }
- }
-
- /**
- * Handle a new authentication request.
- *
- * @param loginContext The {@link LoginContext} for the new authentication request
- * @param servletRequest The servlet request containing the authn request
- * @param servletResponse The associated servlet response.
- */
- private void handleNewAuthnRequest(final LoginContext loginContext, final HttpServletRequest servletRequest,
- final HttpServletResponse servletResponse) throws ServletException, IOException {
-
- boolean forceAuthN = loginContext.getForceAuth();
- boolean passiveAuthN = loginContext.getPassiveAuth();
-
- // set that authentication has been attempted, to prevent processing
- // loops
- loginContext.setAuthenticationAttempted();
-
- // if the profile handler set a list of requested authn methods,
- // evaluate them. otherwise, evaluate the default handler.
- List<String> requestedAuthnMethods = loginContext.getRequestedAuthenticationMethods();
- AuthenticationHandler handler = null;
-
- if (requestedAuthnMethods == null) {
-
- // if no authn methods were specified, try the default handler
-
- if (evaluateHandler(defaultHandler, "default", forceAuthN, passiveAuthN)) {
- handler = defaultHandler;
- loginContext.setAuthenticationMethod(defaultHandlerURI);
- }
-
- } else {
-
- // evaluate all requested authn methods until we find a match.
-
- for (String authnMethodURI : requestedAuthnMethods) {
-
- AuthenticationHandler candidateHandler = handlerMap.get(authnMethodURI);
- if (candidateHandler == null) {
- log.debug("AuthenticationManager: No registered authentication handlers can satisfy the "
- + " requested authentication method " + authnMethodURI);
- continue;
- }
-
- if (evaluateHandler(candidateHandler, authnMethodURI, forceAuthN, passiveAuthN)) {
-
- // we found a match. stop iterating.
- handler = candidateHandler;
- log.info("AuthenticationManager: Using authentication handler " + handler.getClass().getName()
- + " for authentication method " + authnMethodURI);
- loginContext.setAuthenticationMethod(authnMethodURI);
- break;
- }
- }
- }
-
- // if no acceptable handler was found, abort.
- if (handler == null) {
- loginContext.setAuthenticationOK(false);
- loginContext
- .setAuthenticationFailureMessage("No installed AuthenticationHandler can satisfy the authentication request.");
-
- log.error("AuthenticationManager: No registered authentication handlers could satisify any requested "
- + "authentication methods. Unable to process authentication request.");
-
- RequestDispatcher dispatcher = servletRequest.getRequestDispatcher(loginContext.getProfileHandlerURL());
- dispatcher.forward(servletRequest, servletResponse);
- }
-
- // otherwise, forward control to the AuthenticationHandler
- loginContext.setAuthenticationManagerURL(servletRequest.getRequestURI());
- handler.login(servletRequest, servletResponse, loginContext);
- }
-
- /**
- * Handle the "return leg" of an authentication request (i.e. clean up after an authentication handler has run).
- *
- */
- private void finishAuthnRequest(final LoginContext loginContext, final HttpServletRequest servletRequest,
- final HttpServletResponse servletResponse) throws ServletException, IOException {
-
- // if authentication was successful, the authentication handler should
- // have updated the LoginContext with additional information. Use that
- // info to create a Session.
- if (loginContext.getAuthenticationOK()) {
-
- AuthenticationMethodInformation authMethodInfo = new AuthenticationMethodInformationImpl(loginContext
- .getAuthenticationMethod(), loginContext.getAuthenticationInstant(), loginContext
- .getAuthenticationDuration());
-
- InetAddress addr;
- try {
- addr = InetAddress.getByName(servletRequest.getRemoteAddr());
- } catch (Exception ex) {
- addr = null;
- }
-
- Session shibSession = (Session) sessionMgr.createSession(addr, loginContext.getUserID());
- List<AuthenticationMethodInformation> authMethods = shibSession.getAuthenticationMethods();
- authMethods.add(authMethodInfo);
- loginContext.setSessionID(shibSession.getSessionID());
- }
-
- RequestDispatcher dispatcher = servletRequest.getRequestDispatcher(loginContext.getProfileHandlerURL());
- dispatcher.forward(servletRequest, servletResponse);
- }
-
- /**
- * "Stub" method for handling LogoutRequest.
- */
- private void handleLogoutRequest(final HttpServletRequest servletRequest, final HttpServletResponse servletResponse)
- throws ServletException, IOException {
-
- }
-
- /**
- * Evaluate an authenticationhandler against a set of evaluation criteria.
- *
- * @param handler A candiate {@link AuthenticationHandler}
- * @param description A description of the handler
- * @param forceAuthN Is (re)authentication forced?
- * @param passiveAuthN Can the AuthenticationHandler take control of the UI
- *
- * @return <code>true</code> if handler meets the criteria, otherwise <code>false</code>
- */
- private boolean evaluateHandler(final AuthenticationHandler handler, String description, boolean forceAuthN,
- boolean passiveAuthN) {
-
- if (handler == null) {
- return false;
- }
-
- if (forceAuthN && !handler.supportsForceAuthentication()) {
- log.debug("AuthenticationManager: The RequestedAuthnContext required forced authentication, " + "but the "
- + description + " handler does not support that feature.");
- return false;
- }
-
- if (passiveAuthN && !handler.supportsPassive()) {
- log.debug("AuthenticationManager: The RequestedAuthnContext required passive authentication, "
- + "but the " + description + " handler does not support that feature.");
- return false;
- }
-
- return true;
- }
-}
* LoginContexts should be created by a profile handler when authentication is needed. Once control has returned to the
* profile handler, it should remove the LoginContext from the HttpSession.
*
- * The {@link AuthenticationManager} or an {@link AuthenticationHandler} should set the
- * {@link LoginContext#setAuthenticationAttempted()}, {@link LoginContext#setAuthnOK(boolean)},
+ * The {@link AuthenticationEngine} or an {@link AuthenticationHandler} should set the
+ * {@link LoginContext#setAuthenticationAttempted()}, {@link LoginContext#setPrincipalAuthenticated(boolean)},
* {@link LoginContext#setAuthnFailure(String)}, {@link LoginContext#{setAuthenticationDuration(long)}
* {@link LoginContext#setAuthenticationInstant(DateTime)} appropriately.
*
public static final String LOGIN_CONTEXT_KEY = "shib2.logincontext";
/** Serial version UID. */
- private static final long serialVersionUID = 4268661186941572372L;
+ private static final long serialVersionUID = -8764003758734956911L;
/** Entity ID of the relying party. */
private String relyingPartyId;
private boolean authnAttempted;
/** The id of the authenticated user. */
- private String userID;
+ private String principalName;
/** Did authentication succceed? */
- private boolean authenticationOK;
+ private boolean principalAuthenticated;
/** Optional failure message. */
private String authnFailureMessage;
*
* @param authnOK if authentication succeeded;
*/
- public void setAuthenticationOK(boolean authnOK) {
- this.authenticationOK = authnOK;
+ public void setPrincipalAuthenticated(boolean authnOK) {
+ this.principalAuthenticated = authnOK;
}
/**
*
* @return <code>true</code> is the user was successfully authenticated.
*/
- public boolean getAuthenticationOK() {
- return authenticationOK;
+ public boolean isPrincipalAuthenticated() {
+ return principalAuthenticated;
}
/**
*
* @param id The userid.
*/
- public void setUserID(String id) {
- userID = id;
+ public void setPrincipalName(String id) {
+ principalName = id;
}
/**
*
* @return the ID of the user, or <code>null</code> if authentication failed.
*/
- public String getUserID() {
- return userID;
+ public String getPrincipalName() {
+ return principalName;
}
/**
}
/**
- * Return the acceptable authentication handler URIs for authenticating this user. If no authentication methods are
- * preferred the resultant list will be empty.
+ * Return the acceptable authentication handler URIs, in preference order, for authenticating this user. If no
+ * authentication methods are preferred the resultant list will be empty.
*
- * @return an array of URIs
+ * @return an list of authentication method identifiers
*/
public List<String> getRequestedAuthenticationMethods() {
return new ArrayList<String>();
--- /dev/null
+/*
+ * Copyright [2007] [University Corporation for Advanced Internet Development, Inc.]
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.internet2.middleware.shibboleth.idp.authn.impl;
+
+import java.io.IOException;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Logger;
+
+import edu.internet2.middleware.shibboleth.idp.authn.AuthenticationHandler;
+import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
+
+/**
+ * Base class for authentication handlers.
+ */
+public abstract class AbstractAuthenticationHandler implements AuthenticationHandler {
+
+ /** Class logger. */
+ private final Logger log = Logger.getLogger(AbstractAuthenticationHandler.class);
+
+ /** Length of time, in milliseconds, after which a user should be re-authenticated. */
+ private long authenticationDuration;
+
+ /** Whether this handler supports foreced re-authentication. */
+ private boolean supportsForceAuthentication;
+
+ /** Whether this handler supports passive authentication. */
+ private boolean supportsPassive;
+
+ /** {@inheritDoc} */
+ public long getAuthenticationDuration() {
+ return authenticationDuration;
+ }
+
+ /**
+ * Sets the length of time, in milliseconds, after which a user should be re-authenticated.
+ *
+ * @param duration length of time, in milliseconds, after which a user should be re-authenticated
+ */
+ public void setAuthenticationDurection(long duration) {
+ authenticationDuration = duration;
+ }
+
+ /** {@inheritDoc} */
+ public boolean supportsForceAuthentication() {
+ return supportsForceAuthentication;
+ }
+
+ /**
+ * Sets whether this handler supports foreced re-authentication.
+ *
+ * @param supported whether this handler supports foreced re-authentication
+ */
+ public void setSupportsForceAuthentication(boolean supported) {
+ supportsForceAuthentication = supported;
+ }
+
+ /** {@inheritDoc} */
+ public boolean supportsPassive() {
+ return supportsPassive;
+ }
+
+ /**
+ * Sets whether this handler supports passive authentication.
+ *
+ * @param supported whether this handler supports passive authentication.
+ */
+ public void setSupportsPassive(boolean supported) {
+ supportsPassive = supported;
+ }
+
+ /** {@inheritDoc} */
+ public void logout(HttpServletRequest request, HttpServletResponse response, String principal) {
+ // logout not yet supported
+ }
+}
\ No newline at end of file
package edu.internet2.middleware.shibboleth.idp.authn.impl;
import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
-import java.util.List;
import java.util.BitSet;
+import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import javax.servlet.ServletRequest;
-
-import edu.internet2.middleware.shibboleth.idp.authn.AuthenticationHandler;
-import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import javax.servlet.ServletException;
import org.apache.log4j.Logger;
-
import org.joda.time.DateTime;
+import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
+
/**
* IP Address authentication handler.
*
- * This "authenticates" a user based on their IP address. It operates in either
- * default deny or default allow mode, and evaluates a given request against a
- * list of blocked or permitted IPs. It supports both IPv4 and IPv6.
+ * This "authenticates" a user based on their IP address. It operates in either default deny or default allow mode, and
+ * evaluates a given request against a list of blocked or permitted IPs. It supports both IPv4 and IPv6.
*
- * If an Authentication Context Class or DeclRef URI is not specified, it will
- * default to "urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol".
+ * If an Authentication Context Class or DeclRef URI is not specified, it will default to
+ * "urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol".
*/
-public class IPAddressHandler implements AuthenticationHandler {
-
- /**
- * Encapsulates a network address and a netmask on ipList.
- */
- protected class IPEntry {
-
- /** The network address. */
- private final BitSet networkAddress;
-
- /** The netmask. */
- private final BitSet netmask;
-
- /**
- * Construct a new IPEntry given a network address in CIDR format.
- *
- * @param entry
- * A CIDR-formatted network address/netmask
- *
- * @throws UnknownHostException
- * If entry is malformed.
- */
- public IPEntry(String entry) throws UnknownHostException {
-
- // quick sanity checks
- if (entry == null || entry.length() == 0) {
- throw new UnknownHostException("entry is null.");
- }
-
- int cidrOffset = entry.indexOf("/");
- if (cidrOffset == -1) {
- log.error("IPAddressHandler: invalid entry \"" + entry
- + "\" -- it lacks a netmask component.");
- throw new UnknownHostException(
- "entry lacks a netmask component.");
- }
-
- // ensure that only one "/" is present.
- if (entry.indexOf("/", cidrOffset + 1) != -1) {
- log.error("IPAddressHandler: invalid entry \"" + entry
- + "\" -- too many \"/\" present.");
- throw new UnknownHostException(
- "entry has too many netmask components.");
- }
-
- String networkString = entry.substring(0, cidrOffset);
- String netmaskString = entry.substring(cidrOffset + 1, entry
- .length());
-
- InetAddress tempAddr = InetAddress.getByName(networkString);
- networkAddress = byteArrayToBitSet(tempAddr.getAddress());
-
- int masklen = Integer.parseInt(netmaskString);
- int addrlen = networkAddress.length();
-
- // ensure that the netmask isn't too large
- if ((tempAddr instanceof Inet4Address) && (masklen > 32)) {
- throw new UnknownHostException(
- "IPAddressHandler: Netmask is too large for an IPv4 address: "
- + masklen);
- } else if ((tempAddr instanceof Inet6Address) && masklen > 128) {
- throw new UnknownHostException(
- "IPAddressHandler: Netmask is too large for an IPv6 address: "
- + masklen);
- }
-
- netmask = new BitSet(addrlen);
- netmask.set(addrlen - masklen, addrlen, true);
- }
-
- /**
- * Get the network address.
- *
- * @return the network address.
- */
- public BitSet getNetworkAddress() {
- return networkAddress;
- }
-
- /**
- * Get the netmask.
- *
- * @return the netmask.
- */
- public BitSet getNetmask() {
- return netmask;
- }
- }
-
- private static final Logger log = Logger.getLogger(IPAddressHandler.class);
-
- /** The URI of the AuthnContextDeclRef or the AuthnContextClass */
- private String authnMethodURI = "urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol";
-
- /** The username to use for IP-address "authenticated" users. */
- private String username;
-
- /** Are the IPs in ipList a permitted list or a deny list */
- private boolean defaultDeny;
-
- /** The list of denied or permitted IPs */
- private List<IPEntry> ipList;
-
- /** Creates a new instance of IPAddressHandler */
- public IPAddressHandler() {
- }
-
- /**
- * Set the permitted IP addresses.
- *
- * If <code>defaultDeny</code> is <code>true</code> then only the IP
- * addresses in <code>ipList</code> will be "authenticated." If
- * <code>defaultDeny</code> is <code>false</code>, then all IP
- * addresses except those in <code>ipList</code> will be authenticated.
- *
- * @param entries
- * A list of IP addresses (with CIDR masks).
- * @param defaultDeny
- * Does <code>ipList</code> contain a deny or permit list.
- */
- public void setEntries(final List<String> entries, boolean defaultDeny) {
-
- this.defaultDeny = defaultDeny;
- ipList = new CopyOnWriteArrayList<IPEntry>();
-
- for (String addr : entries) {
- try {
- ipList
- .add(new edu.internet2.middleware.shibboleth.idp.authn.impl.IPAddressHandler.IPEntry(
- addr));
- } catch (UnknownHostException ex) {
- log.error("IPAddressHandler: Error parsing entry \"" + addr
- + "\". Ignoring.");
- }
- }
- }
-
- /** @{inheritDoc} */
- public boolean supportsPassive() {
- return true;
- }
-
- /** {@inheritDoc} */
- public boolean supportsForceAuthentication() {
- return true;
- }
-
- /**
- * Set the username to use for all IP-address authenticated users.
- *
- * @param username
- * The username for IP-address authenticated users.
- */
- public void setUsername(String username) {
- this.username = username;
- }
-
- /**
- * Get the username for all IP-address authenticated users.
- *
- * @return The username for IP-address authenticated users.
- */
- public String getUsername() {
- return username;
- }
-
- /** {@inheritDoc} */
- public void logout(final HttpServletRequest request,
- final HttpServletResponse response, final String principal) {
-
- // RequestDispatcher dispatcher = request
- // .getRequestDispatcher(returnLocation);
- // dispatcher.forward(request, response);
- }
-
- /** {@inheritDoc} */
- public void login(final HttpServletRequest request,
- final HttpServletResponse response, final LoginContext loginCtx) {
-
- loginCtx.setAuthenticationAttempted();
- loginCtx.setAuthenticationInstant(new DateTime());
- loginCtx.setUserID(username);
-
- if (defaultDeny) {
- handleDefaultDeny(request, response, loginCtx);
- } else {
- handleDefaultAllow(request, response, loginCtx);
- }
-
- // return control back to the AuthNManager.
- try {
- RequestDispatcher dispatcher = request
- .getRequestDispatcher(loginCtx
- .getAuthenticationManagerURL());
- dispatcher.forward(request, response);
- } catch (ServletException ex) {
- log
- .error(
- "IPAddressHandler: Error returning control to AuthnManager.",
- ex);
- } catch (IOException ex) {
- log
- .error(
- "IPAddressHandler: Error returning control to AuthnManager.",
- ex);
- }
- }
-
- protected void handleDefaultDeny(HttpServletRequest request,
- HttpServletResponse response, LoginContext loginCtx) {
-
- boolean ipAllowed = searchIpList(request);
-
- if (ipAllowed) {
- loginCtx.setAuthenticationOK(true);
- } else {
- loginCtx.setAuthenticationOK(false);
- loginCtx
- .setAuthenticationFailureMessage("The user's IP address is not in the permitted list.");
- }
- }
-
- protected void handleDefaultAllow(HttpServletRequest request,
- HttpServletResponse response, LoginContext loginCtx) {
-
- boolean ipDenied = searchIpList(request);
-
- if (ipDenied) {
- loginCtx.setAuthenticationOK(false);
- loginCtx
- .setAuthenticationFailureMessage("The sser's IP address is in the deny list.");
- } else {
- loginCtx.setAuthenticationOK(true);
- }
- }
-
- /**
- * Search the list of InetAddresses for the client's address.
- *
- * @param request
- * The ServletReqeust
- *
- * @return <code>true</code> if the client's address is in
- * <code>ipList</code>
- */
- private boolean searchIpList(final ServletRequest request) {
-
- boolean found = false;
-
- try {
- InetAddress addr = InetAddress.getByName(request.getRemoteAddr());
- BitSet addrbits = byteArrayToBitSet(addr.getAddress());
-
- for (IPEntry entry : ipList) {
-
- BitSet netaddr = entry.getNetworkAddress();
- BitSet netmask = entry.getNetmask();
-
- addrbits.and(netmask);
- if (addrbits.equals(netaddr)) {
- found = true;
- break;
- }
- }
-
- } catch (UnknownHostException ex) {
- log.error("IPAddressHandler: Error resolving hostname.", ex);
- return false;
- }
-
- return found;
- }
-
- /**
- * Converts a byte array to a BitSet.
- *
- * The supplied byte array is assumed to have the most signifigant bit in
- * element 0.
- *
- * @param bytes
- * the byte array with most signifigant bit in element 0.
- *
- * @return the BitSet
- */
- protected static BitSet byteArrayToBitSet(final byte[] bytes) {
-
- BitSet bits = new BitSet();
-
- for (int i = 0; i < bytes.length * 8; i++) {
- if ((bytes[bytes.length - i / 8 - 1] & (1 << (i % 8))) > 0) {
- bits.set(i);
- }
- }
-
- return bits;
- }
-}
+public class IPAddressHandler extends AbstractAuthenticationHandler {
+
+ /** Class logger. */
+ private final Logger log = Logger.getLogger(IPAddressHandler.class);
+
+ /** The URI of the AuthnContextDeclRef or the AuthnContextClass. */
+ private String authnMethodURI = "urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol";
+
+ /** The username to use for IP-address "authenticated" users. */
+ private String username;
+
+ /** Are the IPs in ipList a permitted list or a deny list. */
+ private boolean defaultDeny;
+
+ /** The list of denied or permitted IPs. */
+ private List<IPEntry> ipList;
+
+ /**
+ * Set the permitted IP addresses.
+ *
+ * If <code>defaultDeny</code> is <code>true</code> then only the IP addresses in <code>ipList</code> will be
+ * "authenticated." If <code>defaultDeny</code> is <code>false</code>, then all IP addresses except those in
+ * <code>ipList</code> will be authenticated.
+ *
+ * @param entries A list of IP addresses (with CIDR masks).
+ * @param defaultDeny Does <code>ipList</code> contain a deny or permit list.
+ */
+ public void setEntries(final List<String> entries, boolean defaultDeny) {
+
+ this.defaultDeny = defaultDeny;
+ ipList = new CopyOnWriteArrayList<IPEntry>();
+
+ for (String addr : entries) {
+ try {
+ ipList.add(new edu.internet2.middleware.shibboleth.idp.authn.impl.IPAddressHandler.IPEntry(addr));
+ } catch (UnknownHostException ex) {
+ log.error("IPAddressHandler: Error parsing entry \"" + addr + "\". Ignoring.");
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ public boolean supportsPassive() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ public boolean supportsForceAuthentication() {
+ return true;
+ }
+
+ /**
+ * Get the username for all IP-address authenticated users.
+ *
+ * @return The username for IP-address authenticated users.
+ */
+ public String getUsername() {
+ return username;
+ }
+
+ /**
+ * Set the username to use for all IP-address authenticated users.
+ *
+ * @param name The username for IP-address authenticated users.
+ */
+ public void setUsername(String name) {
+ username = name;
+ }
+
+ /** {@inheritDoc} */
+ public void login(LoginContext loginContext, HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
+
+ loginContext.setAuthenticationAttempted();
+ loginContext.setAuthenticationInstant(new DateTime());
+ loginContext.setPrincipalName(username);
+
+ if (defaultDeny) {
+ handleDefaultDeny(httpRequest, httpResponse, loginContext);
+ } else {
+ handleDefaultAllow(httpRequest, httpResponse, loginContext);
+ }
+
+ // return control back to the AuthNManager.
+ try {
+ RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(loginContext.getAuthenticationManagerURL());
+ dispatcher.forward(httpRequest, httpResponse);
+ } catch (ServletException ex) {
+ log.error("IPAddressHandler: Error returning control to AuthnManager.", ex);
+ } catch (IOException ex) {
+ log.error("IPAddressHandler: Error returning control to AuthnManager.", ex);
+ }
+ }
+
+ protected void handleDefaultDeny(HttpServletRequest request, HttpServletResponse response, LoginContext loginCtx) {
+
+ boolean ipAllowed = searchIpList(request);
+
+ if (ipAllowed) {
+ loginCtx.setPrincipalAuthenticated(true);
+ } else {
+ loginCtx.setPrincipalAuthenticated(false);
+ loginCtx.setAuthenticationFailureMessage("The user's IP address is not in the permitted list.");
+ }
+ }
+
+ protected void handleDefaultAllow(HttpServletRequest request, HttpServletResponse response, LoginContext loginCtx) {
+
+ boolean ipDenied = searchIpList(request);
+
+ if (ipDenied) {
+ loginCtx.setPrincipalAuthenticated(false);
+ loginCtx.setAuthenticationFailureMessage("The user's IP address is in the deny list.");
+ } else {
+ loginCtx.setPrincipalAuthenticated(true);
+ }
+ }
+
+ /**
+ * Search the list of InetAddresses for the client's address.
+ *
+ * @param request The ServletReqeust
+ *
+ * @return <code>true</code> if the client's address is in <code>ipList</code>
+ */
+ private boolean searchIpList(ServletRequest request) {
+
+ boolean found = false;
+
+ try {
+ InetAddress addr = InetAddress.getByName(request.getRemoteAddr());
+ BitSet addrbits = byteArrayToBitSet(addr.getAddress());
+
+ for (IPEntry entry : ipList) {
+
+ BitSet netaddr = entry.getNetworkAddress();
+ BitSet netmask = entry.getNetmask();
+
+ addrbits.and(netmask);
+ if (addrbits.equals(netaddr)) {
+ found = true;
+ break;
+ }
+ }
+
+ } catch (UnknownHostException ex) {
+ log.error("IPAddressHandler: Error resolving hostname.", ex);
+ return false;
+ }
+
+ return found;
+ }
+
+ /**
+ * Converts a byte array to a BitSet.
+ *
+ * The supplied byte array is assumed to have the most signifigant bit in element 0.
+ *
+ * @param bytes the byte array with most signifigant bit in element 0.
+ *
+ * @return the BitSet
+ */
+ protected BitSet byteArrayToBitSet(final byte[] bytes) {
+
+ BitSet bits = new BitSet();
+
+ for (int i = 0; i < bytes.length * 8; i++) {
+ if ((bytes[bytes.length - i / 8 - 1] & (1 << (i % 8))) > 0) {
+ bits.set(i);
+ }
+ }
+
+ return bits;
+ }
+
+ /**
+ * Encapsulates a network address and a netmask on ipList.
+ */
+ protected class IPEntry {
+
+ /** The network address. */
+ private final BitSet networkAddress;
+
+ /** The netmask. */
+ private final BitSet netmask;
+
+ /**
+ * Construct a new IPEntry given a network address in CIDR format.
+ *
+ * @param entry A CIDR-formatted network address/netmask
+ *
+ * @throws UnknownHostException If entry is malformed.
+ */
+ public IPEntry(String entry) throws UnknownHostException {
+
+ // quick sanity checks
+ if (entry == null || entry.length() == 0) {
+ throw new UnknownHostException("entry is null.");
+ }
+
+ int cidrOffset = entry.indexOf("/");
+ if (cidrOffset == -1) {
+ log.error("IPAddressHandler: invalid entry \"" + entry + "\" -- it lacks a netmask component.");
+ throw new UnknownHostException("entry lacks a netmask component.");
+ }
+
+ // ensure that only one "/" is present.
+ if (entry.indexOf("/", cidrOffset + 1) != -1) {
+ log.error("IPAddressHandler: invalid entry \"" + entry + "\" -- too many \"/\" present.");
+ throw new UnknownHostException("entry has too many netmask components.");
+ }
+
+ String networkString = entry.substring(0, cidrOffset);
+ String netmaskString = entry.substring(cidrOffset + 1, entry.length());
+
+ InetAddress tempAddr = InetAddress.getByName(networkString);
+ networkAddress = byteArrayToBitSet(tempAddr.getAddress());
+
+ int masklen = Integer.parseInt(netmaskString);
+ int addrlen = networkAddress.length();
+
+ // ensure that the netmask isn't too large
+ if ((tempAddr instanceof Inet4Address) && (masklen > 32)) {
+ throw new UnknownHostException("IPAddressHandler: Netmask is too large for an IPv4 address: "
+ + masklen);
+ } else if ((tempAddr instanceof Inet6Address) && masklen > 128) {
+ throw new UnknownHostException("IPAddressHandler: Netmask is too large for an IPv6 address: "
+ + masklen);
+ }
+
+ netmask = new BitSet(addrlen);
+ netmask.set(addrlen - masklen, addrlen, true);
+ }
+
+ /**
+ * Get the network address.
+ *
+ * @return the network address.
+ */
+ public BitSet getNetworkAddress() {
+ return networkAddress;
+ }
+
+ /**
+ * Get the netmask.
+ *
+ * @return the netmask.
+ */
+ public BitSet getNetmask() {
+ return netmask;
+ }
+ }
+}
\ No newline at end of file
import java.io.IOException;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
-
-import org.apache.log4j.Logger;
-import org.joda.time.DateTime;
+import edu.internet2.middleware.shibboleth.idp.authn.AuthenticationEngine;
+import edu.internet2.middleware.shibboleth.idp.authn.AuthenticationHandler;
/**
- * This servlet should be protected by a filter which populates REMOTE_USER. The
- * serlvet will then set the remote user field in a LoginContext.
+ * Extracts the REMOTE_USER and places it in a request attribute to be used by the authentication engine.
*/
public class RemoteUserAuthServlet extends HttpServlet {
- private static final Logger log = Logger
- .getLogger(RemoteUserAuthServlet.class);
-
- public RemoteUserAuthServlet() {
- }
-
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws IOException {
-
- HttpSession httpSession = request.getSession();
-
- Object o = httpSession.getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
- if (!(o instanceof LoginContext)) {
- log
- .error("RemoteUSerAuthServlet - Invalid login context object -- object is not an instance of LoginContext");
- return; // where this will return to, I don't know.
- }
-
- LoginContext loginContext = (LoginContext) o;
-
- loginContext.setAuthenticationInstant(new DateTime());
-
- String remoteUser = request.getRemoteUser();
- if (remoteUser == null || remoteUser.length() == 0) {
- loginContext.setAuthenticationOK(false);
- } else {
- loginContext.setAuthenticationOK(true);
- loginContext.setUserID(remoteUser);
- }
+ /** Serial version UID. */
+ private static final long serialVersionUID = 1968754704168240644L;
- // redirect the user back to the AuthenticationManager
- try {
- RequestDispatcher dispatcher = request
- .getRequestDispatcher(loginContext
- .getAuthenticationManagerURL());
- dispatcher.forward(request, response);
- } catch (ServletException ex) {
- log
- .error(
- "RemoteUserAuthServlet: Error redirecting back to AuthenticationManager",
- ex);
- }
- }
-}
+ /** {@inheritDoc} */
+ public void doPost(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException {
+ httpRequest.setAttribute(AuthenticationHandler.PRINCIPAL_NAME_KEY, httpRequest.getRemoteUser());
+ AuthenticationEngine.returnToAuthenticationEngine(httpRequest, httpResponse);
+ }
+}
\ No newline at end of file
import java.io.IOException;
import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletContext;
import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import edu.internet2.middleware.shibboleth.idp.authn.AuthenticationHandler;
-import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
-
import org.apache.log4j.Logger;
-import org.joda.time.DateTime;
+
+import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
/**
- * {@link AuthenticationHandler} that redirects to servlet protected by a Web
- * Single-Sign-On system.
+ * Authentication Handler that redirects to servlet protected by a Web Single-Sign-On system.
*/
-public class RemoteUserAuthenticationHandler implements AuthenticationHandler {
-
- private static final Logger log = Logger
- .getLogger(RemoteUserAuthenticationHandler.class);
-
- /** The URI of the AuthnContextDeclRef or the AuthnContextClass. */
- private String authnMethodURI;
-
- /** The duration of the authNContext. */
- private long authnDuration;
-
- /** The URL of the SSO-protected servlet. */
- private String servletURL;
-
- private boolean supportsPassive = false;
-
- private boolean supportsForce = false;
-
- /** Creates a new instance of RemoteUserAuthenticationHandler */
- public RemoteUserAuthenticationHandler() {
- }
-
- public void setSupportsPassive(boolean supportsPassive) {
- this.supportsPassive = supportsPassive;
- }
-
- public void setSupportsForce(boolean supportsForce) {
- this.supportsForce = supportsForce;
- }
-
- public boolean supportsPassive() {
- return supportsPassive;
- }
-
- public boolean supportsForceAuthentication() {
- return supportsForce;
- }
-
- /**
- * Set the duration of the AuthnContext.
- *
- * @param duration
- * The duration of the AuthnContext.
- */
- public void setAuthnDuration(long duration) {
- authnDuration = duration;
- }
-
- /**
- * Return the duration of the AuthnContext.
- *
- * @return the duration of the AuthnContext.
- */
- public long getAuthnDuration() {
- return authnDuration;
- }
-
- /**
- * Set the SSO-protected servlet's URL.
- *
- * @param servletURL
- * The URL of the SSO-protected servlet.
- */
- public void setServletURL(String servletURL) {
- this.servletURL = servletURL;
- }
-
- /**
- * Get the URL of the SSO-protected servlet.
- *
- * @return The URL of the SSO-protected servlet.
- */
- public String getServletURL() {
- return servletURL;
- }
-
- /** @{inheritDoc} */
- public void login(final HttpServletRequest request,
- final HttpServletResponse response, final LoginContext loginCtx) {
-
- // set some initial values.
- loginCtx.setAuthenticationAttempted();
- loginCtx.setAuthenticationMethod(authnMethodURI);
- loginCtx.setAuthenticationDuration(authnDuration);
-
- // forward control to the servlet.
- try {
- RequestDispatcher dispatcher = request
- .getRequestDispatcher(servletURL);
- dispatcher.forward(request, response);
- } catch (IOException ex) {
- log
- .error(
- "RemoteUserAuthenticationHandler: Unable to forward control to SSO servlet.",
- ex);
- } catch (ServletException ex) {
- log
- .error(
- "RemoteUserAuthenticationHandler: Unable to forward control to SSO servlet.",
- ex);
- }
-
- }
-
- /** @{inheritDoc} */
- public void logout(final HttpServletRequest request,
- final HttpServletResponse response, String principal) {
-
- }
-
-}
+public class RemoteUserAuthenticationHandler extends AbstractAuthenticationHandler {
+
+ /** Class logger. */
+ private final Logger log = Logger.getLogger(RemoteUserAuthenticationHandler.class);
+
+ /** The URL of the SSO-protected servlet. */
+ private String servletURL;
+
+ /**
+ * Set the SSO-protected servlet's URL.
+ *
+ * @param url The URL of the SSO-protected servlet.
+ */
+ public void setServletURL(String url) {
+ servletURL = url;
+ }
+
+ /**
+ * Get the URL of the SSO-protected servlet.
+ *
+ * @return The URL of the SSO-protected servlet.
+ */
+ public String getServletURL() {
+ return servletURL;
+ }
+
+ /** {@inheritDoc} */
+ public void login(LoginContext loginContext, HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
+
+ // forward control to the servlet.
+ try {
+ RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(servletURL);
+ dispatcher.forward(httpRequest, httpResponse);
+ } catch (IOException ex) {
+ log.error("RemoteUserAuthenticationHandler: Unable to forward control to SSO servlet.", ex);
+ } catch (ServletException ex) {
+ log.error("RemoteUserAuthenticationHandler: Unable to forward control to SSO servlet.", ex);
+ }
+ }
+}
\ No newline at end of file
/**
* Authenticate a username and password against a JAAS source.
*
- * This {@link AuthenticationHandler} requires a JSP to collect a username and
- * password from the user. It also requires a JAAS configuration file to
- * validate the username and password.
+ * This {@link AuthenticationHandler} requires a JSP to collect a username and password from the user. It also requires
+ * a JAAS configuration file to validate the username and password.
*
- * If an Authentication Context Class or DeclRef URI is not specified, it will
- * default to
+ * If an Authentication Context Class or DeclRef URI is not specified, it will default to
* "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport".
*/
-public class UsernamePasswordAuthenticationHandler implements
- AuthenticationHandler {
+public class UsernamePasswordAuthenticationHandler extends AbstractAuthenticationHandler {
- /** Key in an HttpSession for the JAAS configuration name. */
- public static final String JAAS_CONFIG_NAME = "UsernamePasswordAuthenticationHandler.JAAS_CONFIG_NAME";
+ /** Key in an HttpSession for the JAAS configuration name. */
+ public static final String JAAS_CONFIG_NAME = "UsernamePasswordAuthenticationHandler.JAAS_CONFIG_NAME";
- /** Key in an HttpSession for the username. */
- public static final String USERNAME = "UsernamePasswordAuthenticationHandler.USERNAME";
-
- /** Key in an HttpSession for the authentication instant. */
- public static final String AUTHN_INSTANT = "UsernamePasswordAuthenticationHandler.AUTHN_INSTANT";
-
- private static final Logger log = Logger
- .getLogger(UsernamePasswordAuthenticationHandler.class);
+ /** Key in an HttpSession for the username. */
+ public static final String USERNAME = "UsernamePasswordAuthenticationHandler.USERNAME";
- /** The name of the JAAS Configuration to use. */
- protected String jaasConfigurationName;
+ /** Key in an HttpSession for the authentication instant. */
+ public static final String AUTHN_INSTANT = "UsernamePasswordAuthenticationHandler.AUTHN_INSTANT";
- /** The name of the login page. */
- protected String loginURL;
-
- /** The authN duration, in seconds. */
- protected int authnDuration;
-
- /** The URI of the AuthnContextDeclRef or the AuthnContextClass */
- private String authnMethodURI = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport";
-
- public UsernamePasswordAuthenticationHandler() {
- }
-
- /** @{inheritDoc} */
- public boolean supportsPassive() {
- return true;
- }
-
- /** @{inheritDoc} */
- public boolean supportsForceAuthentication() {
- return true;
- }
-
- /** {@inheritDoc} */
- public void login(
- final HttpServletRequest request,
- final HttpServletResponse response,
- final edu.internet2.middleware.shibboleth.idp.authn.LoginContext loginCtx) {
-
- HttpSession session = request.getSession();
-
- // these fields will need to be set, regardless of how we branch.
- loginCtx.setAuthenticationAttempted();
- loginCtx.setAuthenticationMethod(authnMethodURI);
-
- // If forceAuth is set, we must forward to the login JSP.
- if (loginCtx.getForceAuth()) {
-
- if (loginCtx.getPassiveAuth()) {
- log
- .error("UsernamePasswordAuthenticationHandler: Unable to authenticate user: both forceAuthN and passiveAuthnN are set in the login context.");
- redirectControl(loginCtx.getAuthenticationManagerURL(),
- "AuthenticationManager", request, response);
- }
-
- session.setAttribute(JAAS_CONFIG_NAME, jaasConfigurationName);
- redirectControl(loginURL, "login page", request, response);
- }
-
- // If the user has already been authenticated, forceAuth is not set,
- // and the authentication hasn't expired, then populate the LoginCtx
- // and return control to the AuthenticationManager.
- // Otherwise, redirect the user to loginJSPURL to collect a username and
- // password.
-
- // implementation note: There is a race condition here, but I'm not sure
- // how to avoid it. I need a way to instantiate a lock in the session to
- // protect the
- // username and authnInstant fields.
-
- Object o = session.getAttribute(USERNAME);
- if (!(o instanceof String)) {
- log
- .debug("UsernamePasswordAuthenticationHandler: Username attribute found in HttpSession, but it is not a String.");
-
- redirectControl(loginURL, "login page", request, response);
- }
-
- String username = (String) o;
-
- o = session.getAttribute(AUTHN_INSTANT);
- if (!(o instanceof DateTime)) {
- log
- .debug("UsernamePasswordAuthenticationHandler: AuthnInstant attribute found in HttpSession for user "
- + username + ", but it is not a DateTime.");
-
- redirectControl(loginURL, "login page", request, response);
- }
-
- DateTime authnInstant = (DateTime) o;
- DateTime authnExpires = authnInstant.plusSeconds(authnDuration);
- DateTime now = new DateTime();
- if (now.isAfter(authnExpires)) {
- log
- .info("UsernamePasswordAuthenticationHandler: Authentication has expired for user "
- + username);
- redirectControl(loginURL, "login page", request, response);
- }
-
- // the current authentication information is still valid, so return it.
- loginCtx.setAuthenticationOK(true);
- loginCtx.setUserID(username);
- loginCtx.setAuthenticationInstant(authnInstant);
-
- // XXX: adjust for the appropriate units?
- loginCtx.setAuthenticationDuration(authnDuration);
-
- }
-
- /** {@inheritDoc} */
- public void logout(final HttpServletRequest request,
- final HttpServletResponse response, String principal) {
- return;
- }
-
- /**
- * Set the name of the JAAS Configuration to use for user authentication.
- *
- * @param configurationName
- * The name of the JAAS Configuration entry.
- */
- public void setJAASConfigurationName(String configurationName) {
- jaasConfigurationName = configurationName;
- }
-
- /**
- * Get the name of the JAAS Configuraiton to use for user authentication.
- *
- * @return The name of the JAAS Configuration entry.
- */
- public String getJAASConfiguraitonName() {
- return jaasConfigurationName;
- }
-
- /**
- * Set the duration of the authentication.
- *
- * @param duration
- * The duration, in seconds, of the authentication.
- */
- public void setAuthNDuration(int duration) {
- authnDuration = duration;
- }
-
- /**
- * Get the duration of the authentication.
- *
- * @return The duration, in seconds, of the authentication.
- */
- public int getAuthNDuration() {
- return authnDuration;
- }
-
- /**
- * Return control to the AuthNManager.
- *
- * @param url
- * The URL to which control should be redirected.
- * @param urlDescription
- * An optional textual description of <code>url</code>.
- * @param request
- * The HttpServletRequest.
- * @param response
- * The HttpServletResponse.
- */
- protected void redirectControl(String url, String urlDescription,
- final HttpServletRequest request, final HttpServletResponse response) {
-
- try {
- RequestDispatcher dispatcher = request.getRequestDispatcher(url);
- dispatcher.forward(request, response);
- } catch (ServletException ex) {
- log.error(
- "UsernamePasswordAuthenticationHandler: Error returning control to "
- + urlDescription, ex);
- } catch (IOException ex) {
- log.error(
- "UsernamePasswordAuthenticationHandler: Error returning control to "
- + urlDescription, ex);
- }
- }
+ private static final Logger log = Logger.getLogger(UsernamePasswordAuthenticationHandler.class);
+
+ /** The name of the JAAS Configuration to use. */
+ protected String jaasConfigurationName;
+
+ /** The name of the login page. */
+ protected String loginURL;
+
+ /** The authN duration, in seconds. */
+ protected int authnDuration;
+
+ /** The URI of the AuthnContextDeclRef or the AuthnContextClass */
+ private String authnMethodURI = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport";
+
+ public UsernamePasswordAuthenticationHandler() {
+ }
+
+ /** @{inheritDoc} */
+ public boolean supportsPassive() {
+ return true;
+ }
+
+ /** @{inheritDoc} */
+ public boolean supportsForceAuthentication() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ public void login(final edu.internet2.middleware.shibboleth.idp.authn.LoginContext loginContext,
+ final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) {
+
+ HttpSession session = httpRequest.getSession();
+
+ // these fields will need to be set, regardless of how we branch.
+ loginContext.setAuthenticationAttempted();
+ loginContext.setAuthenticationMethod(authnMethodURI);
+
+ // If forceAuth is set, we must forward to the login JSP.
+ if (loginContext.getForceAuth()) {
+
+ if (loginContext.getPassiveAuth()) {
+ log
+ .error("UsernamePasswordAuthenticationHandler: Unable to authenticate user: both forceAuthN and passiveAuthnN are set in the login context.");
+ redirectControl(loginContext.getAuthenticationManagerURL(), "AuthenticationManager", httpRequest,
+ httpResponse);
+ }
+
+ session.setAttribute(JAAS_CONFIG_NAME, jaasConfigurationName);
+ redirectControl(loginURL, "login page", httpRequest, httpResponse);
+ }
+
+ // If the user has already been authenticated, forceAuth is not set,
+ // and the authentication hasn't expired, then populate the LoginCtx
+ // and return control to the AuthenticationManager.
+ // Otherwise, redirect the user to loginJSPURL to collect a username and
+ // password.
+
+ // implementation note: There is a race condition here, but I'm not sure
+ // how to avoid it. I need a way to instantiate a lock in the session to
+ // protect the
+ // username and authnInstant fields.
+
+ Object o = session.getAttribute(USERNAME);
+ if (!(o instanceof String)) {
+ log
+ .debug("UsernamePasswordAuthenticationHandler: Username attribute found in HttpSession, but it is not a String.");
+
+ redirectControl(loginURL, "login page", httpRequest, httpResponse);
+ }
+
+ String username = (String) o;
+
+ o = session.getAttribute(AUTHN_INSTANT);
+ if (!(o instanceof DateTime)) {
+ log.debug("UsernamePasswordAuthenticationHandler: AuthnInstant attribute found in HttpSession for user "
+ + username + ", but it is not a DateTime.");
+
+ redirectControl(loginURL, "login page", httpRequest, httpResponse);
+ }
+
+ DateTime authnInstant = (DateTime) o;
+ DateTime authnExpires = authnInstant.plusSeconds(authnDuration);
+ DateTime now = new DateTime();
+ if (now.isAfter(authnExpires)) {
+ log.info("UsernamePasswordAuthenticationHandler: Authentication has expired for user " + username);
+ redirectControl(loginURL, "login page", httpRequest, httpResponse);
+ }
+
+ // the current authentication information is still valid, so return it.
+ loginContext.setPrincipalAuthenticated(true);
+ loginContext.setPrincipalName(username);
+ loginContext.setAuthenticationInstant(authnInstant);
+
+ // XXX: adjust for the appropriate units?
+ loginContext.setAuthenticationDuration(authnDuration);
+
+ }
+
+ /** {@inheritDoc} */
+ public void logout(final HttpServletRequest request, final HttpServletResponse response, String principal) {
+ return;
+ }
+
+ /**
+ * Set the name of the JAAS Configuration to use for user authentication.
+ *
+ * @param configurationName The name of the JAAS Configuration entry.
+ */
+ public void setJAASConfigurationName(String configurationName) {
+ jaasConfigurationName = configurationName;
+ }
+
+ /**
+ * Get the name of the JAAS Configuraiton to use for user authentication.
+ *
+ * @return The name of the JAAS Configuration entry.
+ */
+ public String getJAASConfiguraitonName() {
+ return jaasConfigurationName;
+ }
+
+ /**
+ * Set the duration of the authentication.
+ *
+ * @param duration The duration, in seconds, of the authentication.
+ */
+ public void setAuthNDuration(int duration) {
+ authnDuration = duration;
+ }
+
+ /**
+ * Get the duration of the authentication.
+ *
+ * @return The duration, in seconds, of the authentication.
+ */
+ public int getAuthNDuration() {
+ return authnDuration;
+ }
+
+ /**
+ * Return control to the AuthNManager.
+ *
+ * @param url The URL to which control should be redirected.
+ * @param urlDescription An optional textual description of <code>url</code>.
+ * @param request The HttpServletRequest.
+ * @param response The HttpServletResponse.
+ */
+ protected void redirectControl(String url, String urlDescription, final HttpServletRequest request,
+ final HttpServletResponse response) {
+
+ try {
+ RequestDispatcher dispatcher = request.getRequestDispatcher(url);
+ dispatcher.forward(request, response);
+ } catch (ServletException ex) {
+ log.error("UsernamePasswordAuthenticationHandler: Error returning control to " + urlDescription, ex);
+ } catch (IOException ex) {
+ log.error("UsernamePasswordAuthenticationHandler: Error returning control to " + urlDescription, ex);
+ }
+ }
}
if (!(o instanceof String)) {
log.error("UsernamePasswordAuthenticationServlet: Unable to authenticate user - Invalid JAAS configuration name specified: " + o.toString());
- loginContext.setAuthenticationOK(false);
+ loginContext.setPrincipalAuthenticated(false);
loginContext.setAuthenticationFailureMessage("Internal configuration error.");
redirectControl(loginContext.getAuthenticationManagerURL(), "AuthenticationManager", request, response);
}
o = request.getAttribute(LOGIN_FORM_USERNAME);
if (!(o instanceof String)) {
log.error("UsernamePasswordAuthenticationServlet: Login form's username is not a String.");
- loginContext.setAuthenticationOK(false);
+ loginContext.setPrincipalAuthenticated(false);
loginContext.setAuthenticationFailureMessage("Internal configuration error.");
- loginContext.setAuthenticationOK(false);
+ loginContext.setPrincipalAuthenticated(false);
loginContext.setAuthenticationFailureMessage("Internal configuration error.");
redirectControl(loginContext.getAuthenticationManagerURL(), "AuthenticationManager", request, response);
o = request.getAttribute(LOGIN_FORM_PASSWORD);
if (!(o instanceof String)) {
log.error("UsernamePasswordAuthenticationServlet: Login form's password is not a String.");
- loginContext.setAuthenticationOK(false);
+ loginContext.setPrincipalAuthenticated(false);
loginContext.setAuthenticationFailureMessage("Internal configuration error.");
- loginContext.setAuthenticationOK(false);
+ loginContext.setPrincipalAuthenticated(false);
loginContext.setAuthenticationFailureMessage("Internal configuration error.");
redirectControl(loginContext.getAuthenticationManagerURL(), "AuthenticationManager", request, response);
log
.debug("UsernamePasswordAuthenticationServlet: Authentication successful for "
+ username);
- idpLoginCtx.setAuthenticationOK(true);
+ idpLoginCtx.setPrincipalAuthenticated(true);
// if JAAS returned multiple usernames, only use the first one.
Set<Principal> principals = jaasLoginCtx.getSubject()
.getPrincipals();
Principal[] temp = new Principal[principals.size()];
principals.toArray(temp);
- idpLoginCtx.setUserID(temp[0].getName());
+ idpLoginCtx.setPrincipalName(temp[0].getName());
} catch (LoginException ex) {
log
.error(
"UsernamePasswordAuthenticationServlet: Error authenticating user.",
ex);
- idpLoginCtx.setAuthenticationOK(false);
+ idpLoginCtx.setPrincipalAuthenticated(false);
}
}
}
Session userSession = getSessionManager().getSession(getUserSessionId(requestContext.getProfileRequest()));
if (userSession != null) {
queryContext.setUserSession(userSession);
- ServiceInformation serviceInfo = userSession.getServiceInformation(requestContext.getRelyingPartyId());
+ ServiceInformation serviceInfo = userSession.getServicesInformation().get(
+ requestContext.getRelyingPartyId());
if (serviceInfo != null) {
String principalAuthenticationMethod = serviceInfo.getAuthenticationMethod().getAuthenticationMethod();
Response samlResponse;
try {
- if (!loginContext.getAuthenticationOK()) {
+ if (!loginContext.isPrincipalAuthenticated()) {
requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null, "User failed authentication"));
throw new ProfileException("User failed authentication");
}
requestContext.setLoginContext(loginContext);
- requestContext.setPrincipalName(loginContext.getUserID());
+ requestContext.setPrincipalName(loginContext.getPrincipalName());
requestContext.setPrincipalAuthenticationMethod(loginContext.getAuthenticationMethod());
Session userSession = getSessionManager().getSession(getUserSessionId(requestContext.getProfileRequest()));
if (userSession != null) {
queryContext.setUserSession(userSession);
- ServiceInformation serviceInfo = userSession.getServiceInformation(requestContext.getRelyingPartyId());
+ ServiceInformation serviceInfo = userSession.getServicesInformation().get(
+ requestContext.getRelyingPartyId());
if (serviceInfo != null) {
String principalAuthenticationMethod = serviceInfo.getAuthenticationMethod().getAuthenticationMethod();
Response samlResponse;
try {
- if (!loginContext.getAuthenticationOK()) {
+ if (!loginContext.isPrincipalAuthenticated()) {
requestContext
.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, StatusCode.AUTHN_FAILED_URI, null));
throw new ProfileException("User failed authentication");
* @return duration of this authentication method
*/
public long getAuthenticationDuration();
+
+ /**
+ * Gets whether this authentication method has expired and is not longer valid for use in constructing new sessions.
+ *
+ * @return whether this authentication method has expired
+ */
+ public boolean isExpired();
}
\ No newline at end of file
package edu.internet2.middleware.shibboleth.idp.session;
import org.joda.time.DateTime;
-import org.opensaml.saml2.core.NameID;
/**
* Information about a service a user has logged in to.
public String getEntityID();
/**
- * Gets the time the user authenticated to the service.
+ * Gets the time the user logged in to the service.
*
- * @return time the user authenticated to the service
+ * @return time the user logged in to the service
*/
- public DateTime getAuthenticationInstant();
+ public DateTime getLoginInstant();
/**
* Gets the authentication method used to log into the service.
* @return authentication method used to log into the service
*/
public AuthenticationMethodInformation getAuthenticationMethod();
-
- /**
- * Gets the NameID used for the subject/user with this service.
- *
- * @return NameID used for the subject/user with this service
- */
- public NameID getSubjectNameID();
}
\ No newline at end of file
package edu.internet2.middleware.shibboleth.idp.session;
-import java.util.List;
+import java.util.Map;
/**
* Session information for user logged into the IdP.
*/
public interface Session extends edu.internet2.middleware.shibboleth.common.session.Session {
-
+
/** Name of the HttpSession attribute a users Shibboleth session Id is bound to. */
public static final String HTTP_SESSION_BINDING_ATTRIBUTE = "ShibbolethSessionId";
*
* @return methods by which the user has authenticated to the IdP
*/
- public List<AuthenticationMethodInformation> getAuthenticationMethods();
-
- /**
- * Gets the information for a service a user is logged into.
- *
- * @param entityId ID of the service
- *
- * @return information for a service a user is logged into or null if the user is not logged into the given service
- */
- public ServiceInformation getServiceInformation(String entityId);
+ public Map<String, AuthenticationMethodInformation> getAuthenticationMethods();
/**
* Gets the services the user has logged in to.
*
* @return services the user has logged in to
*/
- public List<ServiceInformation> getServicesInformation();
+ public Map<String, ServiceInformation> getServicesInformation();
}
\ No newline at end of file
import edu.internet2.middleware.shibboleth.idp.session.AuthenticationMethodInformation;
-
/**
* Information about an authentication method employed by a user.
*/
public class AuthenticationMethodInformationImpl implements AuthenticationMethodInformation {
-
- /** The authentication method (a URI) */
+
+ /** The authentication method (a URI). */
private String authenticationMethod;
-
- /** The timestamp at which authentication occurred */
+
+ /** The timestamp at which authentication occurred. */
private DateTime authenticationInstant;
-
- /** The lifetime of the authentication method */
+
+ /** The lifetime of the authentication method. */
private long authenticationDuration;
-
-
- /**
- * Default constructor
- *
- * @param authenticationMethod The unique identifier for the authentication method.
- * @param authenticationInstant The time the user authenticated with this member.
- * @param authenticationDuration The duration of this authentication method.
- */
- public AuthenticationMethodInformationImpl(final String authenticationMethod,
- final DateTime authenticationInstant, long authenticationDuration) {
-
- if (authenticationMethod == null || authenticationInstant == null
- || authenticationDuration < 0) {
- return;
- }
-
- this.authenticationMethod = authenticationMethod;
- this.authenticationInstant = authenticationInstant;
- this.authenticationDuration = authenticationDuration;
- }
-
-
+
+ /** Time when this method expires. */
+ private DateTime expirationInstant;
+
/**
- * "Cloning" constructor.
- *
- * @param methodInfo The {@link AuthenticationMethodInfo} to duplicate.
+ * Default constructor.
+ *
+ * @param method The unique identifier for the authentication method.
+ * @param instant The time the user authenticated with this member.
+ * @param duration The duration of this authentication method.
*/
- public AuthenticationMethodInformationImpl(final AuthenticationMethodInformation methodInfo) {
-
- if (methodInfo == null) {
- return;
- }
-
- this.authenticationMethod = methodInfo.getAuthenticationMethod();
- this.authenticationInstant = methodInfo.getAuthenticationInstant();
- this.authenticationDuration = methodInfo.getAuthenticationDuration();
+ public AuthenticationMethodInformationImpl(String method, DateTime instant, long duration) {
+
+ if (method == null || instant == null || duration < 0) {
+ throw new IllegalArgumentException("Authentication method, instant, and duration may not be null");
+ }
+
+ authenticationMethod = method;
+ authenticationInstant = instant;
+ authenticationDuration = duration;
+ expirationInstant = instant.plus(duration);
}
-
-
+
/** {@inheritDoc} */
public String getAuthenticationMethod() {
- return this.authenticationMethod;
+ return authenticationMethod;
}
-
-
+
/** {@inheritDoc} */
public DateTime getAuthenticationInstant() {
- return this.authenticationInstant;
+ return authenticationInstant;
}
-
-
+
/** {@inheritDoc} */
public long getAuthenticationDuration() {
- return this.authenticationDuration;
+ return authenticationDuration;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isExpired() {
+ return expirationInstant.isBeforeNow();
}
-
/** {@inheritDoc} */
+ public int hashCode() {
+ return authenticationMethod.hashCode();
+ }
+
+ /** {@inheritDoc} */
public boolean equals(Object obj) {
-
- if (!(obj instanceof AuthenticationMethodInformation)) {
- return false;
- }
-
- AuthenticationMethodInformation amInfo = (AuthenticationMethodInformation)obj;
-
- if (this.getAuthenticationMethod().equals(amInfo.getAuthenticationMethod())
- && this.getAuthenticationInstant().equals(amInfo.getAuthenticationInstant())
- && this.getAuthenticationDuration() == amInfo.getAuthenticationDuration()) {
-
- return true;
- } else {
- return false;
- }
+ if (!(obj instanceof AuthenticationMethodInformation)) {
+ return false;
+ }
+
+ AuthenticationMethodInformation amInfo = (AuthenticationMethodInformation) obj;
+ return authenticationMethod.equals(amInfo.getAuthenticationMethod());
}
-}
+}
\ No newline at end of file
package edu.internet2.middleware.shibboleth.idp.session.impl;
+import org.joda.time.DateTime;
+
import edu.internet2.middleware.shibboleth.idp.session.AuthenticationMethodInformation;
import edu.internet2.middleware.shibboleth.idp.session.ServiceInformation;
-import org.joda.time.DateTime;
-import org.opensaml.saml2.core.NameID;
-
/**
* Information about a service a user has logged in to.
*/
/** Authentication method used to authenticate the user to the service. */
private AuthenticationMethodInformation methodInfo;
- /** Name ID provided to the service. */
- private NameID nameId;
-
/**
* Default constructor.
*
- * @param entityID The unique identifier for the service.
- * @param authenticationInstant The time the user authenticated to the service.
- * @param methodInfo The authentication method used to log into the service.
- * @param nameId The {@link NameID} used for the subject/user with this service.
- *
+ * @param id unique identifier for the service.
+ * @param loginInstant time the user logged in to the service.
+ * @param method authentication method used to log into the service.
*/
- public ServiceInformationImpl(String entityID, DateTime authenticationInstant, AuthenticationMethodInformation methodInfo,
- NameID nameId) {
-
- this.entityID = entityID;
- this.authenticationInstant = authenticationInstant;
- this.methodInfo = methodInfo;
- this.nameId = nameId;
- }
-
- /**
- * Cloning constructor.
- *
- * @param serviceInfo The ServiceInformation instance to duplicate.
- */
- public ServiceInformationImpl(final ServiceInformation serviceInfo) {
-
- if (serviceInfo == null) {
- return;
- }
-
- this.entityID = serviceInfo.getEntityID();
- this.authenticationInstant = serviceInfo.getAuthenticationInstant();
- this.methodInfo = serviceInfo.getAuthenticationMethod();
- this.nameId = serviceInfo.getSubjectNameID();
+ public ServiceInformationImpl(String id, DateTime loginInstant, AuthenticationMethodInformation method) {
+ entityID = id;
+ authenticationInstant = loginInstant;
+ methodInfo = method;
}
/** {@inheritDoc} */
}
/** {@inheritDoc} */
- public DateTime getAuthenticationInstant() {
+ public DateTime getLoginInstant() {
return authenticationInstant;
}
}
/** {@inheritDoc} */
- public NameID getSubjectNameID() {
- return nameId;
+ public int hashCode() {
+ return entityID.hashCode();
}
/** {@inheritDoc} */
}
ServiceInformation si = (ServiceInformation) obj;
- if (this.getEntityID().equals(si.getEntityID())
- && this.getAuthenticationInstant().equals(si.getAuthenticationInstant())
- && this.getSubjectNameID().equals(si.getSubjectNameID())) {
-
- return true;
- }
-
- return false;
+ return entityID.equals(si.getEntityID());
}
}
\ No newline at end of file
package edu.internet2.middleware.shibboleth.idp.session.impl;
import java.net.InetAddress;
-import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import edu.internet2.middleware.shibboleth.common.session.impl.AbstractSession;
* Session information for user logged into the IdP.
*/
public class SessionImpl extends AbstractSession implements Session {
-
+
/** Serial version UID. */
private static final long serialVersionUID = 2927868242208211623L;
/** The list of methods used to authentictate the user. */
- private List<AuthenticationMethodInformation> authnMethods;
+ private HashMap<String, AuthenticationMethodInformation> authnMethods;
/** The list of services to which the user has logged in. */
- private Map<String, ServiceInformation> servicesInformation;
+ private HashMap<String, ServiceInformation> servicesInformation;
/**
* Default constructor.
public SessionImpl(InetAddress presenter, String principal) {
super(presenter, principal);
- authnMethods = new ArrayList<AuthenticationMethodInformation>();
+ authnMethods = new HashMap<String, AuthenticationMethodInformation>();
servicesInformation = new HashMap<String, ServiceInformation>();
}
/** {@inheritDoc} */
- public List<AuthenticationMethodInformation> getAuthenticationMethods() {
+ public Map<String, AuthenticationMethodInformation> getAuthenticationMethods() {
return authnMethods;
}
-
+
/** {@inheritDoc} */
public ServiceInformation getServiceInformation(String entityId) {
return servicesInformation.get(entityId);
}
/** {@inheritDoc} */
- public List<ServiceInformation> getServicesInformation() {
- ArrayList<ServiceInformation> info = new ArrayList<ServiceInformation>();
- for(Map.Entry<String, ServiceInformation> entry : servicesInformation.entrySet()){
- info.add(entry.getValue());
- }
-
- return info;
+ public Map<String, ServiceInformation> getServicesInformation() {
+ return servicesInformation;
}
}
\ No newline at end of file
/**
* Manager of IdP sessions.
+ *
+ * TODO change session map to use storage api
*/
public class SessionManagerImpl implements SessionManager<Session>, ApplicationContextAware {