CAS 4.2 x509 w/ Oracle Database for Authentication (Unable to Throw Exceptions)

12 views
Skip to first unread message

Scot Greber

unread,
Feb 14, 2022, 11:12:27 AM2/14/22
to CAS Community
I lost my CAS resource so I am reaching out to this Group.  We leverage CAS and our login screen allows for username/password as well as DoD CAC Card Login.  The UN/PWD auth works fine and reports back errors to the Login screen as needed.  The CAC Card Login is working fine except when authentication fails.  The reason for the failure is not being reported on the CAS Login screen but is reported in the logs.  It appears the public class X509toIDResolver extends AbstractX509PrincipalResolver {
       
        private DataSource ds;
    private final Logger logger = LoggerFactory.getLogger(getClass());
        String sql = null;

        @Override
        protected String resolvePrincipalInternal(X509Certificate cert) {

only returns a string and does not allow for me to throw an exception so that RequestContextHolder.currentRequestAttributes().setAttribute("mymessage", message, RequestAttributes.SCOPE_REQUEST); reports back to the casLoginView jsp like the UN/PWD does.

What can I do?

On error, the screen just repaints with no message.

I have no idea how to approach.  Thank you in advance.   Providing code snippet below:

package mil.militaryonesource.cas.resolver;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.security.cert.X509Certificate;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;

import org.jasig.cas.adaptors.x509.authentication.principal.AbstractX509PrincipalResolver;

public class X509toIDResolver extends AbstractX509PrincipalResolver {
       
        private DataSource ds;
    private final Logger logger = LoggerFactory.getLogger(getClass());
        String sql = null;

        @Override
        protected String resolvePrincipalInternal(X509Certificate cert) {
        String cn = getCN(cert);
               
        HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
         String aidVal = request.getParameter("AID");
       
        String principalName = null;
        Connection conn=null;
        CallableStatement cs=null;
        ResultSet rs=null;

        logger.debug("CN:"+cn);
        try {
                conn = ds.getConnection();
                cs=conn.prepareCall(sql);
                cs.registerOutParameter(1, java.sql.Types.INTEGER);
                cs.setString(2, "CERTIFICATE");
                cs.setString(3, cn);
                cs.setString(4, "password");
                    cs.setString(5, aidVal);
                cs.registerOutParameter(6, java.sql.Types.INTEGER);
                cs.registerOutParameter(7, java.sql.Types.VARCHAR);
                cs.executeUpdate();
               
                int result = cs.getInt(1);
                if(result==0) { // success
                        principalName = String.valueOf(cs.getInt(6));
                } else {
                        String message = cs.getString(7);
                        RequestContextHolder.currentRequestAttributes().setAttribute("mymessage", message, RequestAttributes.SCOPE_REQUEST);
                                logger.info("User with CN "+cn+" was NOT in the cas_user DB!");
                                return (message);
                }
        } catch (SQLException sqle) {
                    RequestContextHolder.currentRequestAttributes().setAttribute("mymessage", "Unable to Authenticate.", RequestAttributes.SCOPE_REQUEST);
            logger.error(sqle.toString());
            return sqle.toString();
        } finally {
            try {rs.close();} catch (Exception eCloseRs) {}
            try {cs.close();} catch (Exception eCloseStmt) {}
            try {conn.close();} catch (Exception eCloseConn) {}
        }
        logger.info("User "+principalName+" Successfully authenticated!");
        return principalName;
        }
       
        public void setDataSource(DataSource ds) {
                this.ds = ds;
        }
       
        public void setSql(String sql) {
                this.sql = sql;
        }

        private String getCN(X509Certificate cert) {
                String dn = cert.getSubjectX500Principal().getName();
                logger.debug("Certificate DN:"+dn);
                try {
                        LdapName ln = new LdapName(dn);
                        for(Rdn rdn : ln.getRdns()) {
                            if(rdn.getType().equalsIgnoreCase("CN")) {
                                return (String) rdn.getValue();
                            }
                        }
                } catch (Exception e) {
                        logger.error(e.toString());
                }
                return null;
        }

}

The call inside the database for authentication is working well.  I just have no ability to pass back any errors returned to the casLoginView on error.

Any help or direction would be appreciated.

-Scot
Reply all
Reply to author
Forward
0 new messages