package edu.internet2.middleware.shibboleth.idp.authn;
-import edu.internet2.middleware.shibboleth.idp.session.AuthenticationMethodInformation;
-import edu.internet2.middleware.shibboleth.idp.session.impl.AuthenticationMethodInformationImpl;
import java.io.IOException;
import java.util.List;
+import java.util.Map;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import edu.internet2.middleware.shibboleth.idp.authn.AuthenticationHandler;
+import edu.internet2.middleware.shibboleth.idp.session.impl.AuthenticationMethodInformationImpl;
+
+import edu.internet2.middleware.shibboleth.idp.session.AuthenticationMethodInformation;
import edu.internet2.middleware.shibboleth.idp.session.Session;
import edu.internet2.middleware.shibboleth.idp.session.SessionManager;
-import javolution.util.FastList;
import javolution.util.FastMap;
import org.apache.log4j.Logger;
-import org.opensaml.saml2.core.AuthnContextClassRef;
-import org.opensaml.saml2.core.AuthnContextDeclRef;
-import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration;
-import org.opensaml.saml2.core.RequestedAuthnContext;
-
-import org.opensaml.saml2.core.AuthnContextClassRef;
-import org.opensaml.saml2.core.AuthnContextDeclRef;
-import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration;
-import org.opensaml.saml2.core.AuthnRequest;
-import org.opensaml.saml2.core.RequestedAuthnContext;
-
import org.springframework.web.servlet.HttpServletBean;
* Manager responsible for handling authentication requests.
*/
public class AuthenticationManager extends HttpServletBean {
-
+
+ /** log4j. */
private static final Logger log =
- Logger.getLogger(AuthenticationManager.class.getName());
+ Logger.getLogger(AuthenticationManager.class.getName());
- /** SessionManager to be used */
+ /** SessionManager to be used. */
private SessionManager sessionMgr;
- /** Map of URIs onto AuthenticationHandlerInfo */
+ /** Map of URIs onto AuthenticationHandlerInfo. */
private FastMap<String, AuthenticationHandler> handlerMap
- = new FastMap<String, AuthenticationHandler>();
+ = new FastMap<String, AuthenticationHandler>();
- /** The default AuthenticationHandler */
+ /** The default AuthenticationHandler. */
private AuthenticationHandler defaultHandler;
- /* The URI for the default AuthenticationHandler */
+ /* The URI for the default AuthenticationHandler. */
private String defaultHandlerURI;
-
+
/**
- * Gets the session manager to be used
+ * Gets the session manager to be used.
*
* @return session manager to be used
*/
public SessionManager getSessionManager() {
- return this.sessionMgr;
+ return sessionMgr;
}
* @param manager session manager to be used.
*/
public void setSessionManager(final SessionManager manager) {
- this.sessionMgr = 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);
}
/**
- * Add a <String:AuthenticationHandler> mapping to the
+ * 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 handlerInfo Informarmation about the handler.
- *
- * @throws IllegalArgumentExcetption if <code>handlerInfo.getUri()</code> returns </code>null</code>
+ * @param handler The AuthenticationHandler.
*/
public void addHandlerMapping(String uri, AuthenticationHandler handler) {
-
- if (uri == null || handler == null) {
- return;
- }
-
- log.debug("registering " + handler.getClass().getName()
- + " for " + uri);
-
- this.handlerMap.put(uri, handler);
+
+ if (uri == null || handler == null) {
+ return;
+ }
+
+ log.debug("registering " + handler.getClass().getName()
+ + " for " + uri);
+
+ handlerMap.put(uri, handler);
}
/**
- * Register the default {@link AuthenticationHandler}
+ * 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 addDefaultHandler(String uri, AuthenticationHandler handler) {
-
- log.debug("Registering default handler "
- + handler.getClass().getName());
-
- this.defaultHandler = handler;
- this.defaultHandlerURI = uri;
+ public void setDefaultHandler(String uri, AuthenticationHandler handler) {
+
+ log.debug("Registering default handler "
+ + handler.getClass().getName());
+
+ defaultHandler = handler;
+ defaultHandlerURI = uri;
}
* @param uri A URI identifying the authentcation method.
*/
public void removeHandlerMapping(String uri) {
-
- if (uri == null) {
- return;
- }
-
- log.debug("unregistering handler for " + uri);
-
- this.handlerMap.remove(uri);
+
+ if (uri == null) {
+ return;
+ }
+
+ log.debug("unregistering handler for " + uri);
+
+ handlerMap.remove(uri);
}
/**
- * Primary entrypoint for the AuthnManager
+ * 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("Invalid parameters in AuthenticationManager's doPost().");
- return;
- }
-
- HttpSession httpSession = req.getSession();
- if (httpSession == null) {
- log.error("Unable to retrieve HttpSession from request.");
- return;
- }
- Object o = httpSession.getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
- if (! (o instanceof LoginContext)) {
- log.error("Invalid login context object -- object is not an instance of LoginContext.");
- return;
- }
- LoginContext loginContext = (LoginContext)o;
-
- // If authentication has been attempted, don't try it again.
- if (loginContext.getAuthenticationAttempted()) {
- this.handleNewAuthnRequest(loginContext, req, resp);
- } else {
- this.finishAuthnRequest(loginContext, req, resp);
- }
-
-
+ HttpServletResponse resp) throws ServletException, IOException {
+
+ if (req == null || resp == null) {
+ log.error("Invalid parameters in AuthenticationManager's doPost().");
+ return;
+ }
+
+ HttpSession httpSession = req.getSession();
+ Object o = httpSession.getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
+ if (! (o instanceof LoginContext)) {
+ log.error("Invalid login context object -- object is not an instance of LoginContext.");
+ 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 {@link AuthnRequest}s
+ * 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 isPassive = loginContext.getPassiveAuth();
-
- RequestedAuthnContext authnCtx = null;
-
- // if loginContext is really a Saml2LoginContext, extract the
- // (possibly null) RequestedAuthnContext.
- if (loginContext instanceof Saml2LoginContext) {
- Saml2LoginContext samlLoginContext = (Saml2LoginContext)loginContext;
- authnCtx = samlLoginContext.getRequestedAuthnContext();
- }
-
- // if no registered handler can evaluate the request, abort.
- AuthenticationHandler handler =
- this.getHandler(authnCtx, loginContext, forceAuthN, isPassive);
- if (handler == null) {
- loginContext.setAuthenticationAttempted();
- loginContext.setAuthenticationOK(false);
- loginContext.setAuthenticationFailureMessage("No installed AuthenticationHandlers can satisfy the authentication request.");
-
- RequestDispatcher dispatcher =
- servletRequest.getRequestDispatcher(loginContext.getProfileHandlerURL());
- dispatcher.forward(servletRequest, servletResponse);
- }
-
- // otherwise, forward control to the authenticationhandler
- ServletContext servletContext = this.getServletContext();
- loginContext.setAuthenticationManagerURL(servletRequest.getPathInfo());
- handler.setReturnLocation(servletRequest.getPathInfo());
- handler.login(servletRequest, servletResponse,
- loginContext.getPassiveAuth(), loginContext.getForceAuth());
+ 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("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("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("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
+ ServletContext servletContext = getServletContext();
+ loginContext.setAuthenticationManagerURL(servletRequest.getPathInfo());
+ handler.login(servletRequest, servletResponse, loginContext);
}
*
*/
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()) {
-
- AuthenticationMethodInformationImpl authMethodInfo =
- new AuthenticationMethodInformationImpl(loginContext.getAuthenticationMethod(),
- loginContext.getAuthenticationInstant(), loginContext.getAuthenticationDuration());
-
- Session shibSession = this.getSessionManager().createSession();
- List<AuthenticationMethodInformation> authMethods = shibSession.getAuthenticationMethods();
- authMethods.add(authMethodInfo);
- loginContext.setSessionID(shibSession.getSessionID());
- }
-
- RequestDispatcher dispatcher =
- servletRequest.getRequestDispatcher(loginContext.getProfileHandlerURL());
- dispatcher.forward(servletRequest, servletResponse);
- }
+ 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()) {
+
+ AuthenticationMethodInformationImpl authMethodInfo =
+ new AuthenticationMethodInformationImpl(loginContext.getAuthenticationMethod(),
+ loginContext.getAuthenticationInstant(), loginContext.getAuthenticationDuration());
+
+ Session shibSession = getSessionManager().createSession();
+ List<AuthenticationMethodInformation> authMethods = shibSession.getAuthenticationMethods();
+ authMethods.add(authMethodInfo);
+ loginContext.setSessionID(shibSession.getSessionID());
+ }
- /**
- * "Stub" method for handling LogoutRequest
- */
- private void handleLogoutRequest(final HttpServletRequest servletRequest,
- final HttpServletResponse servletResponse) throws ServletException, IOException {
-
+ RequestDispatcher dispatcher =
+ servletRequest.getRequestDispatcher(loginContext.getProfileHandlerURL());
+ dispatcher.forward(servletRequest, servletResponse);
}
/**
- * Examine an {@link RequestedAuthnContext} against a list of installed
- * {@link AuthenticationHandler}s. If an acceptable handler is found, return
- * a reference to it. Otherwise return <code>null</code>. The {@link LoginContext}
- * is updated to reflect the selected authentication method's URI.
- *
- * @param authnCtx A {@link RequestedAuthnContext}
- * @param loginCtx The {@link LoginContext}
- * @param forceAuthN Should authentication be forced.
- * @param passiveAuthN Must authentication happen without UI control.
- *
- * @return A reference to an {@link AuthenticationHandler} or <code>null</code>.
+ * "Stub" method for handling LogoutRequest.
*/
- private AuthenticationHandler getHandler(final RequestedAuthnContext authnCtx,
- final LoginContext loginCtx, boolean forceAuthN, boolean passiveAuthN) {
-
- // if no context is specified, evaluate the default handler
- if (authnCtx == null) {
- loginCtx.setAuthenticationMethod(this.defaultHandlerURI);
- return this.evaluateHandler(this.defaultHandler, "default",
- forceAuthN, passiveAuthN);
- }
-
-
- // For the immediate future, we only support the "exact" comparator.
- AuthnContextComparisonTypeEnumeration comparator = authnCtx.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 FastList<String>();
- List<AuthnContextClassRef> authnClasses = authnCtx.getAuthnContextClassRefs();
- List<AuthnContextDeclRef> authnDeclRefs = authnCtx.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 no AuthnContextClasses or AuthnContextDeclRefs were actually specified,
- // evaluate the default handler
- if (requestedAuthnMethods.size() == 0) {
- return this.evaluateHandler(this.defaultHandler, "default",
- forceAuthN, passiveAuthN);
- }
-
-
- // evaluate all requested authn methods until we find a match.
- AuthenticationHandler handler = null;
- for (String s : requestedAuthnMethods) {
-
- AuthenticationHandler candidateHandler = this.handlerMap.get(s);
- if (candidateHandler == null) {
- log.debug("No registered authentication handlers can satisfy the "
- + " requested authentication method " + s);
- continue;
- }
-
- handler = this.evaluateHandler(candidateHandler, s, forceAuthN, passiveAuthN);
-
- if (handler != null) {
- // we found a match. stop iterating.
- log.info("Using authentication handler " + handler.getClass().getName()
- + " for authentication method " + s);
- loginCtx.setAuthenticationMethod(s);
- break;
- }
- }
-
- if (handler == null) {
- log.error("No registered authentication handlers could satisify any requested "
- + "authentication methods. Unable to process authentication request.");
- }
-
- return (handler);
+ private void handleLogoutRequest(final HttpServletRequest servletRequest,
+ final HttpServletResponse servletResponse) throws ServletException, IOException {
+
}
* @param description A description of the handler
* @param forceAuthN Is (re)authentication forced?
* @param passiveAuthN Can the AuthenticationHandler take control of the UI
- * @return A reference to an {@link AuthenticationHandler} or <code>null</code>.
+ *
+ * @return <code>true</code> if handler meets the criteria, otherwise <code>false</code>
*/
- private AuthenticationHandler evaluateHandler(final AuthenticationHandler handler,
- String description, boolean forceAuthN, boolean passiveAuthN) {
-
- if (handler == null) {
- return (null);
- }
-
- if (forceAuthN && !handler.supportsForceAuthentication()) {
- log.debug("The RequestedAuthnContext required forced authentication, "
- + "but the " + description + " handler does not support that feature.");
- return (null);
- }
-
- if (passiveAuthN && !handler.supportsPassive()) {
- log.debug("The RequestedAuthnContext required passive authentication, "
- + "but the " + description + " handler does not support that feature.");
- return (null);
- }
-
- return handler;
+ private boolean evaluateHandler(final AuthenticationHandler handler,
+ String description, boolean forceAuthN, boolean passiveAuthN) {
+
+ if (handler == null) {
+ return false;
+ }
+
+ if (forceAuthN && !handler.supportsForceAuthentication()) {
+ log.debug("The RequestedAuthnContext required forced authentication, "
+ + "but the " + description + " handler does not support that feature.");
+ return false;
+ }
+
+ if (passiveAuthN && !handler.supportsPassive()) {
+ log.debug("The RequestedAuthnContext required passive authentication, "
+ + "but the " + description + " handler does not support that feature.");
+ return false;
+ }
+
+ return true;
}
}
*
* The {@link AuthenticationManager} or an {@link AuthenticationHandler} should set the
* {@link LoginContext#setAuthenticationAttempted()}, {@link LoginContext#setAuthnOK(boolean)},
- * {@link LoginContext#setAuthnFailure(String)} appropriately.
+ * {@link LoginContext#setAuthnFailure(String)}, {@link LoginContext#{setAuthenticationDuration(long)}
+ * {@link LoginContext#setAuthenticationInstant(DateTime)} appropriately.
*
*/
public class LoginContext {
/** Should user authentication be forced */
- private boolean forceAuth = false;
+ protected boolean forceAuth = false;
/** Must authentication not interact with the UI */
- private boolean passiveAuth = false;
+ protected boolean passiveAuth = false;
/** a catch-all map for other properties */
- private Map<String, Object> propsMap = new FastMap<String, Object>();
+ protected Map<String, Object> propsMap = new FastMap<String, Object>();;
/** The ProfileHandler URL */
- private String profileHandlerURL;
+ protected String profileHandlerURL;
/** The AuthenticationManager's URL */
- private String authnManagerURL;
+ protected String authnManagerURL;
/** has authentication been attempted yet */
- private boolean authnAttempted = false;
+ protected boolean authnAttempted = false;
/** The id of the authenticated user */
- private String userID;
+ protected String userID;
/** Did authentication succceed? */
- private boolean authenticationOK;
+ protected boolean authenticationOK;
/** Optional failure message */
- private String authnFailureMessage;
+ protected String authnFailureMessage;
/** The instant of authentication */
- private DateTime authnInstant;
+ protected DateTime authnInstant;
/** The duration of authentication */
- private long authnDuration;
+ protected long authnDuration;
/** The method used to authenticate the user */
- private String authnMethod;
+ protected String authnMethod;
/** The session id */
- private String sessionID;
+ protected String sessionID;
/** Creates a new instance of LoginContext */
*/
public LoginContext(boolean forceAuth, boolean passiveAuth) {
- this.forceAuth = forceAuth;
- this.passiveAuth = passiveAuth;
+ forceAuth = forceAuth;
+ passiveAuth = passiveAuth;
}
* @return <code>true</code> if the authentication manager must reauth the user.
*/
public boolean getForceAuth() {
- return this.forceAuth;
+ return forceAuth;
}
* @return <code>true</code> if the authentication manager must not interact with the users UI.
*/
public boolean getPassiveAuth() {
- return this.passiveAuth;
+ return passiveAuth;
}
* @return The object, or <code>null</code> is no object exists for the key.
*/
public Object getProperty(String key) {
- return this.propsMap.get(key);
+ return propsMap.get(key);
}
* @param obj The object to associate with key.
*/
public void setProperty(String key, final Object obj) {
- this.propsMap.put(key, obj);
+ propsMap.put(key, obj);
}
*
* @param authnOK if authentication succeeded;
*/
- public void setAuthnOK(boolean authnOK) {
+ public void setAuthenticationOK(boolean authnOK) {
this.authenticationOK = authnOK;
}
*
* @return <code>true</code> is the user was successfully authenticated.
*/
- public boolean getAuthnOK() {
- return this.authenticationOK;
+ public boolean getAuthenticationOK() {
+ return authenticationOK;
}
*
* @param failureMessage A description of why authN failed.
*/
- public void setAuthnFailureMessage(String failureMessage) {
- this.authnFailureMessage = failureMessage;
+ public void setAuthenticationFailureMessage(String failureMessage) {
+ authnFailureMessage = failureMessage;
}
*
* @return The failure message, or <code>null</code> is none was set.
*/
- public String getAuthnFailureMessage() {
- return this.authnFailureMessage;
+ public String getAuthenticationFailureMessage() {
+ return authnFailureMessage;
}
* while processing a request.
*/
public void setAuthenticationAttempted() {
- this.authnAttempted = true;
+ authnAttempted = true;
}
* Returns if authentication has been attempted for this user.
*/
public boolean getAuthenticationAttempted() {
- return this.authnAttempted;
+ return authnAttempted;
}
* @return the ID of the user, or <code>null</code> if authentication failed.
*/
public String getUserID() {
- return this.userID;
+ return userID;
}
* @return the URL of the profile handler that is invoking the Authentication Manager.
*/
public String getProfileHandlerURL() {
- return this.profileHandlerURL;
+ return profileHandlerURL;
}
* @param profileHandlerURL The URL of the profile handler that invoked the AuthenticationManager/
*/
public void setProfileHandlerURL(String profileHandlerURL) {
- this.profileHandlerURL = profileHandlerURL;
+ this.profileHandlerURL = profileHandlerURL;
}
*
* @return the URL of the AuthenticationManager.
*/
- public String getAuthnManagerURL() {
- return this.authnManagerURL;
+ public String getAuthenticationManagerURL() {
+ return authnManagerURL;
}
*
* @param authnManagerURL the URL of the AuthenticationManager.
*/
- public void setAuthnManagerURL(String authnManagerURL) {
- this.authnManagerURL = authnManagerURL;
+ public void setAuthenticationManagerURL(String authnManagerURL) {
+ this.authnManagerURL = authnManagerURL;
}
* @return The instant of authentication, or <code>null</code> if none was set.
*/
public DateTime getAuthenticationInstant() {
- return this.authnInstant;
+ return authnInstant;
}
* @param authnInstant The instant of authentication.
*/
public void setAuthenticationInstant(final DateTime authnInstant) {
- this.authnInstant = authnInstant;
+ this.authnInstant = authnInstant;
}
* @return The duration of authentication, or zero if none was set.
*/
public long getAuthenticationDuration() {
- return this.authnDuration;
+ return authnDuration;
}
* @param authnDuration The duration of authentication.
*/
public void setAuthenticationDuration(long authnDuration) {
- this.authnDuration = authnDuration;
+ this.authnDuration = authnDuration;
}
* @return The method used to authenticate the user.
*/
public String getAuthenticationMethod() {
- return this.authnMethod;
+ return authnMethod;
}
* @param authnMethod The method used to authenticate the user.
*/
public void setAuthenticationMethod(String authnMethod) {
- this.authnMethod = authnMethod;
+ this.authnMethod = authnMethod;
}
* @return the Session id.
*/
public String getSessionID() {
- return this.sessionID;
+ return sessionID;
}
* @param sessionID the Session ID
*/
public void setSessionID(String sessionID) {
- this.sessionID = 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;
}
}
package edu.internet2.middleware.shibboleth.idp.authn;
-import bsh.This;
-import java.util.Map;
-import javolution.util.FastMap;
+import java.util.List;
+import javolution.util.FastList;
+
+import org.apache.log4j.Logger;
+
+import org.opensaml.saml2.core.AuthnContextClassRef;
+import org.opensaml.saml2.core.AuthnContextDeclRef;
+import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration;
+import org.opensaml.saml2.core.AuthnRequest;
import org.opensaml.saml2.core.RequestedAuthnContext;
+
/**
- * Login context created by a profile handler and interpreted
- * by the authentication package.
+ * A SAML 2.0 {@link LoginContext}.
*
- * Two properties are tracked by default:
- *
- * <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.
+ * 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 LoginContext */
- public Saml2LoginContext() {
- }
-
-
/**
- * Creates a new instance of LoginContext
+ * Creates a new instance of Saml2LoginContext.
*
- * @param forceAuth if the authentication manager must reauth the user.
- * @param passiveAuth if the authentication manager must not interact with the users UI.
- * @param ctx The requested login context.
+ * @param authnRequest A SAML 2.0 Authentication Request.
*/
- public Saml2LoginContext(boolean forceAuth, boolean passiveAuth, final RequestedAuthnContext ctx) {
+ public Saml2LoginContext(AuthnRequest authnRequest) {
- super(forceAuth, passiveAuth);
-
- this.ctx = ctx;
- }
+ if (authnRequest != null) {
+ forceAuth = authnRequest.isForceAuthn();
+ passiveAuth = authnRequest.isPassive();
+ ctx = authnRequest.getRequestedAuthnContext();
+ }
+ }
- /**
- * Set the requested authentication context.
+ /**
+ * This method evaluates a SAML2 {@link RequestedAuthnContext}
+ * and returns the list of requested authentication method URIs.
*
- * @param ctx The requested authN context.
+ * 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 void setRequestedAuthnContext(RequestedAuthnContext ctx) {
- this.ctx = ctx;
- }
+ 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 FastList<String>();
+ List<AuthnContextClassRef> authnClasses = ctx.getAuthnContextClassRefs();
+ List<AuthnContextDeclRef> authnDeclRefs = ctx.getAuthnContextDeclRefs();
- /**
- * Returns the requested authentication context.
- *
- * @return the RequestedAuthnContext, or <code>null</code> if none was set.
- */
- public RequestedAuthnContext getRequestedAuthnContext() {
- return this.ctx;
- }
+ 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);
+ }
+
+ }
}