Tim,

On 7/12/22 10:09, Tim K wrote:
Hello,
I currently have a custom realm in Tomcat 9 that uses form
authentication (j_username/j_password POST to j_security_check).  I'm
looking to create a secondary way to establish an authenticated
session.  I want to allow trusted sources to be able to POST a
username param to a specific URL and establish an authenticated
session with that provided username (I know, seems kind of scary, but
it's just for a proof of concept right now).  Eventually this
secondary method may replace the custom realm all together, i.e.
offloading authentication to an external provider.

I've searched the list and other internet sources which led me to
attempt to extend the ValveBase to try and set a UserPrincipal on the
org.apache.catalina.connector.Request.  I was trying to intercept POST
requests to a new specific RequestURI and if the provided username
param is acceptable, I do the request.setUserPrincipal with the role
that is required.

Am I going down the wrong path to accomplish this?  When the valve
code gets hit, It doesn't seem that the user is really getting
authenticated; I believe because the request comes/goes and the
principal is getting lost when the request is done...

Also, I'm getting a 405 error on the actual POST, even though it
appears the principal gets established for that request...  Not sure
if this has something to do with the JSESSIONID cookie...

There isn't much magic to what Tomcat does for a (normal) login. It just does the authentication (which you will handle) and shoves an object into the user's session. You can't access that object, but it drives the return values of Request.getUserPrincipal() and Request.isInRole().

You can very easily use a Filter to wrap the request in your own wrapper (hint: extend HttpRequestWrapper) and return whatever values from wherever you want them to go. You can maintain your own authentication source however you want. The big advantage to doing this is that you will end up with a container-agnostic solution that will continue to work even if Tomcat changes something it does. It's always best to have a standards-based solution.

Something like this:

class MyAuthenticationFilter implements Filter {
public void filter(ServletRequest request, ServletResponse response, FilterChain chain) {
    // Do all the checking/casting for HttpStuff
    request = new MyAuthenticationWrapper(httpRequest);

    chain.doFilter(request, response);
  }

  static interface MyPrincipal extends Principal {
    public boolean isInRole(String role);
  }

  static class MyAuthenticationWrapper extends HttpServletRequestWrapper {
    public static final String PRINCIPAL_KEY = "my.auth.principal";

    public MyAuthenticationWrapper(HttpServletRequest request) {
      super(request);
    }

    public Principal getUserPrincipal() {
      Principal p = super.getUserPrincipal();

      if(null == p) {
        HttpSession session = getSession(false);

        if(null != session) {
          p = (Principal)session.getAttribute(PRINCIPAL_KEY);
        }
      }

      return p;
    }

    public boolean isInRole(String role) {
      Principal p = getUserPrincipal();
      if(p instanceof MyPrincipal) {
        return ((MyPrincipal)p).isInRole(role);
      } else {
        // Let the container decide
        return super.isInRole(role);
      }
    }

    // TODO: If you are really paranoid about your code, you should
    //       wrap getSession to return a wrapped session that doesn't
    //       allow anyone to set (or maybe even GET) a value for the
    //       PRINCIPAL_KEY.
  }
}

Now, to authenticate your users using your hand-wavy authentication, just shove something into the HttpSession which implements MyPrincipal. Users who login as usual will get a "normal" principal and the container will handle the role checks. If you put an object in the session with the right key, this will work because the container doesn't have a container-managed Principal.

-chris

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

Reply via email to