*/
public class AuthenticationManager extends HttpServletBean {
- /** log4j. */
- private static 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.
- 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;
- }
+ /** 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;
+ }
}
package edu.internet2.middleware.shibboleth.idp.authn;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.joda.time.DateTime;
/**
- * Login context created by a profile handler and interpreted by the
- * authentication package.
+ * Login context created by a profile handler and interpreted by the authentication package.
*
* Two properties are tracked by default:
*
- * <code>forceAuth</code> - Should user authentiation be forced.
- * <code>passiveAuth</code> - Should user authentication not control the UI.
+ * <code>forceAuth</code> - Should user authentiation be forced. <code>passiveAuth</code> - Should user
+ * authentication not control the UI.
*
- * A Map<String, Object> is provided to store other properties.
- * Alternatively, a profile handler may create a subclass of LoginContext with
- * extra fields.
+ * A Map<String, Object> is provided to store other properties. Alternatively, a profile handler may create a
+ * subclass of LoginContext with extra fields.
*
- * 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.
+ * 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)},
- * {@link LoginContext#setAuthnFailure(String)},
- * {@link LoginContext#{setAuthenticationDuration(long)}
+ * The {@link AuthenticationManager} or an {@link AuthenticationHandler} should set the
+ * {@link LoginContext#setAuthenticationAttempted()}, {@link LoginContext#setAuthnOK(boolean)},
+ * {@link LoginContext#setAuthnFailure(String)}, {@link LoginContext#{setAuthenticationDuration(long)}
* {@link LoginContext#setAuthenticationInstant(DateTime)} appropriately.
*
*/
-public class LoginContext {
-
- /** the key in a HttpSession where login contexts are stored */
- public static final String LOGIN_CONTEXT_KEY = "shib2.logincontext";
-
- /** Should user authentication be forced */
- protected boolean forceAuth = false;
-
- /** Must authentication not interact with the UI */
- protected boolean passiveAuth = false;
-
- /** a catch-all map for other properties */
- protected Map<String, Object> propsMap = new ConcurrentHashMap<String, Object>();;
-
- /** The ProfileHandler URL */
- protected String profileHandlerURL;
-
- /** The AuthenticationManager's URL */
- protected String authnManagerURL;
-
- /** has authentication been attempted yet */
- protected boolean authnAttempted = false;
-
- /** The id of the authenticated user */
- protected String userID;
-
- /** Did authentication succceed? */
- protected boolean authenticationOK;
-
- /** Optional failure message */
- protected String authnFailureMessage;
-
- /** The instant of authentication */
- protected DateTime authnInstant;
-
- /** The duration of authentication */
- protected long authnDuration;
-
- /** The method used to authenticate the user */
- protected String authnMethod;
-
- /** The session id */
- protected String sessionID;
-
- /** Creates a new instance of LoginContext */
- public LoginContext() {
- }
-
- /**
- * Creates a new instance of LoginContext
- *
- * @param forceAuth
- * if the authentication manager must reauth the user.
- * @param passiveAuth
- * if the authentication manager must not interact with the users
- * UI.
- */
- public LoginContext(boolean forceAuth, boolean passiveAuth) {
-
- forceAuth = forceAuth;
- passiveAuth = passiveAuth;
- }
-
- /**
- * Returns if authentication must be forced.
- *
- * @return <code>true</code> if the authentication manager must reauth the
- * user.
- */
- public boolean getForceAuth() {
- return forceAuth;
- }
-
- /**
- * Returns if authentication must be passive.
- *
- * @return <code>true</code> if the authentication manager must not
- * interact with the users UI.
- */
- public boolean getPassiveAuth() {
- return passiveAuth;
- }
-
- /**
- * Sets if authentication must be forced.
- *
- * @param forceAuth
- * if the authentication manager must reauth the user.
- */
- public void setForceAuth(boolean forceAuth) {
- this.forceAuth = forceAuth;
- }
-
- /**
- * Sets if authentication must be passive.
- *
- * @param passiveAuth
- * if the authentication manager must not interact with the users
- * UI.
- */
- public void setPassiveAuth(boolean passiveAuth) {
- this.passiveAuth = passiveAuth;
- }
-
- /**
- * Get an optional property object.
- *
- * @param key
- * The key in the properites Map.
- *
- * @return The object, or <code>null</code> is no object exists for the
- * key.
- */
- public Object getProperty(String key) {
- return propsMap.get(key);
- }
-
- /**
- * Sets an optional property object.
- *
- * If an object is already associated with key, it will be overwritten.
- *
- * @param key
- * The key to set.
- * @param obj
- * The object to associate with key.
- */
- public void setProperty(String key, final Object obj) {
- propsMap.put(key, obj);
- }
-
- /**
- * Sets if authentication succeeded.
- *
- * @param authnOK
- * if authentication succeeded;
- */
- public void setAuthenticationOK(boolean authnOK) {
- this.authenticationOK = authnOK;
- }
-
- /**
- * Returns if authentication succeeded.
- *
- * @return <code>true</code> is the user was successfully authenticated.
- */
- public boolean getAuthenticationOK() {
- return authenticationOK;
- }
-
- /**
- * Sets the optional authentication failure message.
- *
- * @param failureMessage
- * A description of why authN failed.
- */
- public void setAuthenticationFailureMessage(String failureMessage) {
- authnFailureMessage = failureMessage;
- }
-
- /**
- * Returns the optional authentication failure message.
- *
- * @return The failure message, or <code>null</code> is none was set.
- */
- public String getAuthenticationFailureMessage() {
- return authnFailureMessage;
- }
-
- /**
- * Set if authentication has been attempted.
- *
- * This method should be called by an {@link AuthenticationHandler} while
- * processing a request.
- */
- public void setAuthenticationAttempted() {
- authnAttempted = true;
- }
-
- /**
- * Returns if authentication has been attempted for this user.
- */
- public boolean getAuthenticationAttempted() {
- return authnAttempted;
- }
-
- /**
- * Sets the ID of the authenticated user.
- *
- * @param userID
- * The userid.
- */
- public void setUserID(String userID) {
- this.userID = userID;
- }
-
- /**
- * Returns the ID of the authenticated user.
- *
- * @return the ID of the user, or <code>null</code> if authentication
- * failed.
- */
- public String getUserID() {
- return userID;
- }
-
- /**
- * Gets the ProfileHandler URL.
- *
- * @return the URL of the profile handler that is invoking the
- * Authentication Manager.
- */
- public String getProfileHandlerURL() {
- return profileHandlerURL;
- }
-
- /**
- * Sets the ProfileHandler URL.
- *
- * @param profileHandlerURL
- * The URL of the profile handler that invoked the
- * AuthenticationManager/
- */
- public void setProfileHandlerURL(String profileHandlerURL) {
- this.profileHandlerURL = profileHandlerURL;
- }
-
- /**
- * Gets the AuthenticationManager URL.
- *
- * @return the URL of the AuthenticationManager.
- */
- public String getAuthenticationManagerURL() {
- return authnManagerURL;
- }
-
- /**
- * Sets the AuthenticationManager's URL.
- *
- * @param authnManagerURL
- * the URL of the AuthenticationManager.
- */
- public void setAuthenticationManagerURL(String authnManagerURL) {
- this.authnManagerURL = authnManagerURL;
- }
-
- /**
- * Gets the authentication instant.
- *
- * @return The instant of authentication, or <code>null</code> if none was
- * set.
- */
- public DateTime getAuthenticationInstant() {
- return authnInstant;
- }
-
- /**
- * Sets the authentication instant.
- *
- * @param authnInstant
- * The instant of authentication.
- */
- public void setAuthenticationInstant(final DateTime authnInstant) {
- this.authnInstant = authnInstant;
- }
-
- /**
- * Gets the duration of authentication.
- *
- * @return The duration of authentication, or zero if none was set.
- */
- public long getAuthenticationDuration() {
- return authnDuration;
- }
-
- /**
- * Sets the duration of authentication.
- *
- * @param authnDuration
- * The duration of authentication.
- */
- public void setAuthenticationDuration(long authnDuration) {
- this.authnDuration = authnDuration;
- }
-
- /**
- * Gets the method used to authenticate the user.
- *
- * @return The method used to authenticate the user.
- */
- public String getAuthenticationMethod() {
- return authnMethod;
- }
-
- /**
- * Sets the method used to authenticate the user.
- *
- * @param authnMethod
- * The method used to authenticate the user.
- */
- public void setAuthenticationMethod(String authnMethod) {
- this.authnMethod = authnMethod;
- }
-
- /**
- * Gets the {@link Session} ID
- *
- * @return the Session id.
- */
- public String getSessionID() {
- return sessionID;
- }
-
- /**
- * Sets the {@link Session} ID
- *
- * @param sessionID
- * the Session ID
- */
- public void setSessionID(String sessionID) {
- this.sessionID = sessionID;
- }
-
- /**
- * Return the acceptable authentication handler URIs for authenticating this
- * user. If no authentication methods are preferred, this method will return
- * <code>null</code>.
- *
- * @return an array of URIs, or <code>null</code>.
- */
- public String[] getRequestedAuthenticationMethods() {
-
- return null;
- }
+public class LoginContext implements Serializable {
+
+ /** the key in a HttpSession where login contexts are stored. */
+ public static final String LOGIN_CONTEXT_KEY = "shib2.logincontext";
+
+ /** Serial version UID. */
+ private static final long serialVersionUID = 4268661186941572372L;
+
+ /** Entity ID of the relying party. */
+ private String relyingPartyId;
+
+ /** Should user authentication be forced. */
+ private boolean forceAuth;
+
+ /** Must authentication not interact with the UI. */
+ private boolean passiveAuth;
+
+ /** a catch-all map for other properties. */
+ private Map<String, Serializable> propsMap = new ConcurrentHashMap<String, Serializable>();
+
+ /** The ProfileHandler URL. */
+ private String profileHandlerURL;
+
+ /** The AuthenticationManager's URL. */
+ private String authnManagerURL;
+
+ /** has authentication been attempted yet. */
+ private boolean authnAttempted;
+
+ /** The id of the authenticated user. */
+ private String userID;
+
+ /** Did authentication succceed? */
+ private boolean authenticationOK;
+
+ /** Optional failure message. */
+ private String authnFailureMessage;
+
+ /** The instant of authentication. */
+ private DateTime authnInstant;
+
+ /** The duration of authentication. */
+ private long authnDuration;
+
+ /** The method used to authenticate the user. */
+ private String authnMethod;
+
+ /** The session id. */
+ private String sessionID;
+
+ /** Creates a new instance of LoginContext. */
+ public LoginContext() {
+ }
+
+ /**
+ * Creates a new instance of LoginContext.
+ *
+ * @param force if the authentication manager must reauth the user.
+ * @param passive if the authentication manager must not interact with the users UI.
+ */
+ public LoginContext(boolean force, boolean passive) {
+
+ forceAuth = force;
+ passiveAuth = passive;
+ }
+
+ /**
+ * Gets the entity ID of the relying party.
+ *
+ * @return entity ID of the relying party
+ */
+ public String getRelyingPartyId() {
+ return relyingPartyId;
+ }
+
+ /**
+ * Gets the entity ID of the relying party.
+ *
+ * @param id entity ID of the relying party
+ */
+ public void setRelyingParty(String id) {
+ relyingPartyId = id;
+ }
+
+ /**
+ * Returns if authentication must be forced.
+ *
+ * @return <code>true</code> if the authentication manager must reauth the user.
+ */
+ public boolean getForceAuth() {
+ return forceAuth;
+ }
+
+ /**
+ * Returns if authentication must be passive.
+ *
+ * @return <code>true</code> if the authentication manager must not interact with the users UI.
+ */
+ public boolean getPassiveAuth() {
+ return passiveAuth;
+ }
+
+ /**
+ * Sets if authentication must be forced.
+ *
+ * @param forceAuth if the authentication manager must reauth the user.
+ */
+ public void setForceAuth(boolean forceAuth) {
+ this.forceAuth = forceAuth;
+ }
+
+ /**
+ * Sets if authentication must be passive.
+ *
+ * @param passiveAuth if the authentication manager must not interact with the users UI.
+ */
+ public void setPassiveAuth(boolean passiveAuth) {
+ this.passiveAuth = passiveAuth;
+ }
+
+ /**
+ * Get an optional property object.
+ *
+ * @param key The key in the properites Map.
+ *
+ * @return The object, or <code>null</code> is no object exists for the key.
+ */
+ public Object getProperty(String key) {
+ return propsMap.get(key);
+ }
+
+ /**
+ * Sets an optional property object.
+ *
+ * If an object is already associated with key, it will be overwritten.
+ *
+ * @param key The key to set.
+ * @param obj The object to associate with key.
+ */
+ public void setProperty(String key, final Serializable obj) {
+ propsMap.put(key, obj);
+ }
+
+ /**
+ * Sets if authentication succeeded.
+ *
+ * @param authnOK if authentication succeeded;
+ */
+ public void setAuthenticationOK(boolean authnOK) {
+ this.authenticationOK = authnOK;
+ }
+
+ /**
+ * Returns if authentication succeeded.
+ *
+ * @return <code>true</code> is the user was successfully authenticated.
+ */
+ public boolean getAuthenticationOK() {
+ return authenticationOK;
+ }
+
+ /**
+ * Sets the optional authentication failure message.
+ *
+ * @param failureMessage A description of why authN failed.
+ */
+ public void setAuthenticationFailureMessage(String failureMessage) {
+ authnFailureMessage = failureMessage;
+ }
+
+ /**
+ * Returns the optional authentication failure message.
+ *
+ * @return The failure message, or <code>null</code> is none was set.
+ */
+ public String getAuthenticationFailureMessage() {
+ return authnFailureMessage;
+ }
+
+ /**
+ * Set if authentication has been attempted.
+ *
+ * This method should be called by an {@link AuthenticationHandler} while processing a request.
+ */
+ public void setAuthenticationAttempted() {
+ authnAttempted = true;
+ }
+
+ /**
+ * Returns if authentication has been attempted for this user.
+ *
+ * @return if authentication has been attempted for this user
+ */
+ public boolean getAuthenticationAttempted() {
+ return authnAttempted;
+ }
+
+ /**
+ * Sets the ID of the authenticated user.
+ *
+ * @param id The userid.
+ */
+ public void setUserID(String id) {
+ userID = id;
+ }
+
+ /**
+ * Returns the ID of the authenticated user.
+ *
+ * @return the ID of the user, or <code>null</code> if authentication failed.
+ */
+ public String getUserID() {
+ return userID;
+ }
+
+ /**
+ * Gets the ProfileHandler URL.
+ *
+ * @return the URL of the profile handler that is invoking the Authentication Manager.
+ */
+ public String getProfileHandlerURL() {
+ return profileHandlerURL;
+ }
+
+ /**
+ * Sets the ProfileHandler URL.
+ *
+ * @param profileHandlerURL The URL of the profile handler that invoked the AuthenticationManager/
+ */
+ public void setProfileHandlerURL(String profileHandlerURL) {
+ this.profileHandlerURL = profileHandlerURL;
+ }
+
+ /**
+ * Gets the AuthenticationManager URL.
+ *
+ * @return the URL of the AuthenticationManager.
+ */
+ public String getAuthenticationManagerURL() {
+ return authnManagerURL;
+ }
+
+ /**
+ * Sets the AuthenticationManager's URL.
+ *
+ * @param authnManagerURL the URL of the AuthenticationManager.
+ */
+ public void setAuthenticationManagerURL(String authnManagerURL) {
+ this.authnManagerURL = authnManagerURL;
+ }
+
+ /**
+ * Gets the authentication instant.
+ *
+ * @return The instant of authentication, or <code>null</code> if none was set.
+ */
+ public DateTime getAuthenticationInstant() {
+ return authnInstant;
+ }
+
+ /**
+ * Sets the authentication instant.
+ *
+ * @param authnInstant The instant of authentication.
+ */
+ public void setAuthenticationInstant(final DateTime authnInstant) {
+ this.authnInstant = authnInstant;
+ }
+
+ /**
+ * Gets the duration of authentication.
+ *
+ * @return The duration of authentication, or zero if none was set.
+ */
+ public long getAuthenticationDuration() {
+ return authnDuration;
+ }
+
+ /**
+ * Sets the duration of authentication.
+ *
+ * @param authnDuration The duration of authentication.
+ */
+ public void setAuthenticationDuration(long authnDuration) {
+ this.authnDuration = authnDuration;
+ }
+
+ /**
+ * Gets the method used to authenticate the user.
+ *
+ * @return The method used to authenticate the user.
+ */
+ public String getAuthenticationMethod() {
+ return authnMethod;
+ }
+
+ /**
+ * Sets the method used to authenticate the user.
+ *
+ * @param authnMethod The method used to authenticate the user.
+ */
+ public void setAuthenticationMethod(String authnMethod) {
+ this.authnMethod = authnMethod;
+ }
+
+ /**
+ * Gets the {@link Session} ID
+ *
+ * @return the Session id.
+ */
+ public String getSessionID() {
+ return sessionID;
+ }
+
+ /**
+ * Sets the {@link Session} ID
+ *
+ * @param sessionID the Session ID
+ */
+ public void setSessionID(String sessionID) {
+ this.sessionID = sessionID;
+ }
+
+ /**
+ * Return the acceptable authentication handler URIs for authenticating this user. If no authentication methods are
+ * preferred the resultant list will be empty.
+ *
+ * @return an array of URIs
+ */
+ public List<String> getRequestedAuthenticationMethods() {
+ return new ArrayList<String>();
+ }
}
package edu.internet2.middleware.shibboleth.idp.authn;
+import java.io.Serializable;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
import java.util.List;
-import java.util.LinkedList;
-import org.apache.log4j.Logger;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.apache.log4j.Logger;
+import org.opensaml.Configuration;
import org.opensaml.saml2.core.AuthnContextClassRef;
-import org.opensaml.saml2.core.AuthnContextDeclRef;
import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration;
+import org.opensaml.saml2.core.AuthnContextDeclRef;
import org.opensaml.saml2.core.AuthnRequest;
import org.opensaml.saml2.core.RequestedAuthnContext;
+import org.opensaml.xml.io.Marshaller;
+import org.opensaml.xml.io.MarshallingException;
+import org.opensaml.xml.io.Unmarshaller;
+import org.opensaml.xml.io.UnmarshallingException;
+import org.opensaml.xml.util.XMLHelper;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
/**
* A SAML 2.0 {@link LoginContext}.
*
* This class can interpret {@link RequestedAuthnContext} and act accordingly.
*/
-public class Saml2LoginContext extends LoginContext {
-
- private static final Logger log = Logger.getLogger(Saml2LoginContext.class);
-
- /** The {@link RequestedAuthnContext} */
- private RequestedAuthnContext ctx;
-
- /**
- * Creates a new instance of Saml2LoginContext.
- *
- * @param authnRequest
- * A SAML 2.0 Authentication Request.
- */
- public Saml2LoginContext(AuthnRequest authnRequest) {
-
- if (authnRequest != null) {
- forceAuth = authnRequest.isForceAuthn();
- passiveAuth = authnRequest.isPassive();
- ctx = authnRequest.getRequestedAuthnContext();
- }
- }
-
- /**
- * This method evaluates a SAML2 {@link RequestedAuthnContext} and returns
- * the list of requested authentication method URIs.
- *
- * If the AuthnQuery did not contain a RequestedAuthnContext, this method
- * will return <code>null</code>.
- *
- * @return An array of authentication method URIs, or <code>null</code>.
- */
- public String[] getRequestedAuthenticationMethods() {
-
- if (ctx == null)
- return null;
-
- // For the immediate future, we only support the "exact" comparator.
- // XXX: we should probably throw an exception or somehow indicate this
- // as an error to the caller.
- AuthnContextComparisonTypeEnumeration comparator = ctx.getComparison();
- if (comparator != null
- && comparator != AuthnContextComparisonTypeEnumeration.EXACT) {
- log
- .error("Unsupported comparision operator ( "
- + comparator
- + ") in RequestedAuthnContext. Only exact comparisions are supported.");
- return null;
- }
-
- // build a list of all requested authn classes and declrefs
- List<String> requestedAuthnMethods = new LinkedList<String>();
- List<AuthnContextClassRef> authnClasses = ctx
- .getAuthnContextClassRefs();
- List<AuthnContextDeclRef> authnDeclRefs = ctx.getAuthnContextDeclRefs();
-
- if (authnClasses != null) {
- for (AuthnContextClassRef classRef : authnClasses) {
- if (classRef != null) {
- String s = classRef.getAuthnContextClassRef();
- if (s != null) {
- requestedAuthnMethods.add(s);
- }
- }
- }
- }
-
- if (authnDeclRefs != null) {
- for (AuthnContextDeclRef declRef : authnDeclRefs) {
- if (declRef != null) {
- String s = declRef.getAuthnContextDeclRef();
- if (s != null) {
- requestedAuthnMethods.add(s);
- }
- }
- }
- }
-
- if (requestedAuthnMethods.size() == 0) {
- return null;
- } else {
- String[] methods = new String[requestedAuthnMethods.size()];
- return requestedAuthnMethods.toArray(methods);
- }
-
- }
-}
+public class Saml2LoginContext extends LoginContext implements Serializable {
+
+ /** Serial version UID. */
+ private static final long serialVersionUID = -2518779446947534977L;
+
+ /** Class logger. */
+ private final Logger log = Logger.getLogger(Saml2LoginContext.class);
+
+ /** Serialized authentication request. */
+ private String serialAuthnRequest;
+
+ /** Unmarshalled authentication request. */
+ private transient AuthnRequest authnRequest;
+
+ /**
+ * Creates a new instance of Saml2LoginContext.
+ *
+ * @param relyingParty entity ID of the relying party
+ * @param request SAML 2.0 Authentication Request
+ *
+ * @throws MarshallingException thrown if the given request can not be marshalled and serialized into a string
+ */
+ public Saml2LoginContext(String relyingParty, AuthnRequest request) throws MarshallingException {
+ if (relyingParty == null || request == null) {
+ throw new IllegalArgumentException("SAML 2 authentication request and relying party ID may not be null");
+ }
+
+ serialAuthnRequest = serializeRequest(request);
+ authnRequest = request;
+ setForceAuth(authnRequest.isForceAuthn());
+ setPassiveAuth(authnRequest.isPassive());
+ setRelyingParty(relyingParty);
+ }
+
+ /**
+ * Gets the authentication request that started the login process.
+ *
+ * @return authentication request that started the login process
+ *
+ * @throws UnmarshallingException thrown if the serialized form on the authentication request can be unmarshalled
+ */
+ public AuthnRequest getAuthenticationRequest() throws UnmarshallingException {
+ if (authnRequest == null) {
+ authnRequest = deserializeRequest(serialAuthnRequest);
+ }
+
+ return authnRequest;
+ }
+
+ /**
+ * Gets the requested authentication context information from the authentication request.
+ *
+ * @return requested authentication context information or null
+ */
+ public RequestedAuthnContext getRequestedAuthenticationContext() {
+ try {
+ AuthnRequest request = getAuthenticationRequest();
+ return request.getRequestedAuthnContext();
+ } catch (UnmarshallingException e) {
+ return null;
+ }
+ }
+
+ /**
+ * This method evaluates a SAML2 {@link RequestedAuthnContext} and returns the list of requested authentication
+ * method URIs.
+ *
+ * If the AuthnQuery did not contain a RequestedAuthnContext, this method will return <code>null</code>.
+ *
+ * @return An array of authentication method URIs, or <code>null</code>.
+ */
+ public List<String> getRequestedAuthenticationMethods() {
+ ArrayList<String> requestedMethods = new ArrayList<String>();
+
+ RequestedAuthnContext authnContext = getRequestedAuthenticationContext();
+ if (authnContext == null) {
+ return requestedMethods;
+ }
+
+ // For the immediate future, we only support the "exact" comparator.
+ AuthnContextComparisonTypeEnumeration comparator = authnContext.getComparison();
+ if (comparator != null && comparator != AuthnContextComparisonTypeEnumeration.EXACT) {
+ log.error("Unsupported comparision operator ( " + comparator
+ + ") in RequestedAuthnContext. Only exact comparisions are supported.");
+ return null;
+ }
+
+ // build a list of all requested authn classes and declrefs
+ List<AuthnContextClassRef> authnClasses = authnContext.getAuthnContextClassRefs();
+ List<AuthnContextDeclRef> authnDeclRefs = authnContext.getAuthnContextDeclRefs();
+
+ if (authnClasses != null) {
+ for (AuthnContextClassRef classRef : authnClasses) {
+ if (classRef != null) {
+ requestedMethods.add(classRef.getAuthnContextClassRef());
+ }
+ }
+ }
+
+ if (authnDeclRefs != null) {
+ for (AuthnContextDeclRef declRef : authnDeclRefs) {
+ if (declRef != null) {
+ requestedMethods.add(declRef.getAuthnContextDeclRef());
+ }
+ }
+ }
+
+ return requestedMethods;
+ }
+
+ /**
+ * Serializes an authentication request into a string.
+ *
+ * @param request the request to serialize
+ *
+ * @return the serialized form of the string
+ *
+ * @throws MarshallingException thrown if the request can not be marshalled and serialized
+ */
+ protected String serializeRequest(AuthnRequest request) throws MarshallingException {
+ Marshaller marshaller = Configuration.getMarshallerFactory().getMarshaller(request);
+ Element requestElem = marshaller.marshall(request);
+ StringWriter writer = new StringWriter();
+ XMLHelper.writeNode(requestElem, writer);
+ return writer.toString();
+ }
+
+ /**
+ * Deserailizes an authentication request from a string.
+ *
+ * @param request request to deserialize
+ *
+ * @return the request XMLObject
+ *
+ * @throws UnmarshallingException thrown if the request can no be deserialized and unmarshalled
+ */
+ protected AuthnRequest deserializeRequest(String request) throws UnmarshallingException {
+ DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
+ try {
+ DocumentBuilder docBuilder = builderFactory.newDocumentBuilder();
+ InputSource requestInput = new InputSource(new StringReader(request));
+ Element requestElem = docBuilder.parse(requestInput).getDocumentElement();
+ Unmarshaller unmarshaller = Configuration.getUnmarshallerFactory().getUnmarshaller(requestElem);
+ return (AuthnRequest) unmarshaller.unmarshall(requestElem);
+ } catch (Exception e) {
+ throw new UnmarshallingException("Unable to read serialized authentication request");
+ }
+ }
+
+}
\ No newline at end of file