Hi there,

for an application to be deployed on a TomEE we need the support for two 
factor authentication.
Are there planned development efforts going into that direction?

As temporary workaround we patched the class FormAuthenticator, so that a 
second factor (a 2fa token) is additionlly evaluated. 
This patch is in the style of AuthenticRoast, an solution available for 
Tomcat 1.6.

Here the code patch in pseudo code:



package org.apache.catalina.authenticator;

[original code omitted with imports]

/**
 * An <b>Authenticator</b> and <b>Valve</b> implementation of FORM BASED 
Authentication, as
 * described in the Servlet API Specification, Version 2.2.
 */
public class FormAuthenticator extends AuthenticatorBase {

  [original code omitted]


  // --------------------------------------------------------- Public 
Methods

  /**
   * Authenticate the user making this request, based on the specified 
login configuration. Return
   * <code>true</code> if any specified constraint has been satisfied, or 
<code>false</code> if we
   * have created a response challenge already.
   *
   * @param request Request we are processing
   * @param response Response we are creating
   * @param config Login configuration describing how authentication 
should be performed
   *
   * @exception IOException if an input/output error occurs
   */
  @Override
  public boolean authenticate(Request request, HttpServletResponse 
response, LoginConfig config) throws IOException {

    // References to objects we will need later
    Session session = null;
    // Have we already authenticated someone?
    Principal principal = request.getUserPrincipal();
    String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
 
    [original code omitted]

    // Yes -- Acknowledge the request, validate the specified credentials
    // and redirect to the error page if they are not correct
    request.getResponse().sendAcknowledgement();
    Realm realm = context.getRealm();
    if (characterEncoding != null) {
      request.setCharacterEncoding(characterEncoding);
    }

    String username = request.getParameter(Constants.FORM_USERNAME);
    String password = request.getParameter(Constants.FORM_PASSWORD);
    if (log.isDebugEnabled()) {
      log.debug("Authenticating username '" + username + "'");
    }


    // BEGIN --- Customized code for two factor authentication Part I --- 
BEGIN
    String password2factor = request.getParameter("j_2fa");
    // A customized Realm Class which implements a second factor 
authentication
    final TwoFactorRealm twoFactorRealm = new TwoFactorRealm(...);
    boolean twoFactorSuccessful = twoFactorRealm.authenticate(username, 
password2factor);
    if (log.isWarnEnabled() && !twoFactorSuccessful) {
      log.warn("Authentication 2FA failed for user " + username);
    }
    // END --- Customized code for two factor authentication Part I --- 
END
 

    principal = realm.authenticate(username, password);

    // BEGIN --- Customized code for two factor authentication Part II --- 
BEGIN
    if (principal == null || !twoFactorSuccessful) {
      log.warn("Authentication of '" + username + "' failed: [principal=" 
+ principal + "], [twoFactorSuccessful=" + twoFactorSuccessful + "]");
      forwardToErrorPage(request, response, config);
      return (false);
    }
    // END --- Customized code for two factor authentication Part II --- 
END

    if (log.isDebugEnabled()) {
      log.debug("Authentication of '" + username + "' was successful");
    }

    if (session == null) {
      session = request.getSessionInternal(false);
    }
    if (session == null) {
      if (containerLog.isDebugEnabled()) {
        containerLog.debug("User took so long to log on the session 
expired");
      }
      if (landingPage == null) {
        response.sendError(HttpServletResponse.SC_REQUEST_TIMEOUT, 
sm.getString("authenticator.sessionExpired"));
      } else {
        // Make the authenticator think the user originally requested
        // the landing page
        String uri = request.getContextPath() + landingPage;
        SavedRequest saved = new SavedRequest();
        saved.setMethod("GET");
        saved.setRequestURI(uri);
        saved.setDecodedRequestURI(uri);
 request.getSessionInternal(true).setNote(Constants.FORM_REQUEST_NOTE, 
saved);
        response.sendRedirect(response.encodeRedirectURL(uri));
      }
      return (false);
    }

    // Save the authenticated Principal in our session
    session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal);

    // Save the username and password as well
    session.setNote(Constants.SESS_USERNAME_NOTE, username);
    session.setNote(Constants.SESS_PASSWORD_NOTE, password);

    // Redirect the user to the original request URI (which will cause
    // the original request to be restored)
    requestURI = savedRequestURL(session);
    if (log.isDebugEnabled()) {
      log.debug("Redirecting to original '" + requestURI + "'");
    }
    if (requestURI == null) {
      if (landingPage == null) {
        response.sendError(HttpServletResponse.SC_BAD_REQUEST, 
sm.getString("authenticator.formlogin"));
      } else {
        // Make the authenticator think the user originally requested
        // the landing page
        String uri = request.getContextPath() + landingPage;
        SavedRequest saved = new SavedRequest();
        saved.setMethod("GET");
        saved.setRequestURI(uri);
        saved.setDecodedRequestURI(uri);
        session.setNote(Constants.FORM_REQUEST_NOTE, saved);
        response.sendRedirect(response.encodeRedirectURL(uri));
      }
    } else {
      response.sendRedirect(response.encodeRedirectURL(requestURI));
    }
    return (false);

  }

  [original code omitted] 
 
}

Best regards,

Marco
--
Dipl.-Inf. Marco Bellavia 
Software Engineering

DENIC eG
Kaiserstraße 75-77
60329 Frankfurt am Main
GERMANY

Angaben nach § 25a Absatz 1 GenG:
DENIC eG (Sitz: Frankfurt am Main)
Vorstand: Helga Krüger, Andreas Musielak, Carsten Schiefner, Dr. Jörg 
Schweiger 
Vorsitzender des Aufsichtsrats: Thomas Keller
Eingetragen unter Nr. 770 im Genossenschaftsregister, Amtsgericht 
Frankfurt am Main

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to