4 Replies Latest reply on Nov 7, 2006 7:48 PM by soshah

    Custom principal class

      Hi

      I have written my own principal classwhcih extends org.jboss.security.SimplePrincipal

      Also I have written my own LoginModule whcih extends org.jboss.security.auth.spi.AbstractServerLoginModule

      In my module when I call createIdentity method, after that I confirm that identity (i.e. my Principal obejct) is of type MyPrincapl only.

      in the login-config.xml I have defined principalClass option

      [<application-policy name = "eluminate">

      <login-module code="com.coremetrics.sso.module.DBLoginModule"
      flag = "required">
      <module-option name="debug">true</module-option>
      <module-option name="unauthenticatedIdentity">guest</module-option>
      <module-option name="principalClass">com.coremetrics.sso.principal.MyPrincipal</module-option>
      </login-module>

      </application-policy>]



      Everything works fine for me and when I login user gets authenticated sucessfully, however when I do request.getUserPrincipal() I get a principal Object whcih is of type org.jboss.security.SimplePrincipal.

      Also when I print that Principal Object, System.out , it calls the toString mthod defined in MyPrincipal class.

      Same thing happens when I print
      org.jboss.security.SecurityAssociation.getSubject().getPrincipals()


      Please can anyone tell me what I am missing

      Thanks
      Nipun

        • 1. Re: Custom principal class

          When I do request.getUserPrincipal I shd get object of type MyPrincipal

          • 2. Re: Custom principal class
            anil.saldhana

            Try using the following option on your login module:

            password-stacking=useFirstPass

            Is your login module the only LM in your application policy?

            I think on our end, we will have to create a test case for this scenario and see if there are any issues.


            Or why don't you override the UsernamePasswordLoginModule?
            http://wiki.jboss.org/wiki/Wiki.jsp?page=UsingCustomPrincpalsWith

            • 3. Re: Custom principal class

              Hi

              Thanks for your reponse, defining module option as such has not helped
              <module-option name="password-stacking">useFirstPass</module-option>

              Still I am not able to get my custom defined principal.

              Is it compulsory to use UsernamePasswordLoginModule, I think there shd be a way to achive this.

              Following is my Principal class and LoginModileClass
              [
              package com.coremetrics.sso.principal;


              import java.io.Serializable;
              import java.util.TimeZone;

              import org.jboss.security.SimplePrincipal;



              public class MyPrincipal extends SimplePrincipal implements Serializable {

              //private static final long serialVersionUID = 8601244958865076474L;

              /**
              * @serial
              */
              private String name;



              private String userPassword;

              private String locale;

              private TimeZone timeZone;

              private String userName;

              private int verticalId;

              private String userEmail;

              private String homePageURL;

              private String clientName;

              public String getHomePageURL() {
              return homePageURL;
              }

              public void setHomePageURL(String homePageURL) {
              this.homePageURL = homePageURL;
              }

              public String getClientName() {
              return clientName;
              }

              public void setClientName(String clientName) {
              this.clientName = clientName;
              }

              public String getUserEmail() {
              return userEmail;
              }

              public void setUserEmail(String userEmail) {
              this.userEmail = userEmail;
              }

              public int getVerticalId() {
              return verticalId;
              }

              public void setVerticalId(int verticalId) {
              this.verticalId = verticalId;
              }

              /**
              * Create a SamplePrincipal with a Sample username.
              *
              *
              *
              * @param name
              * the Sample username for this user.
              *
              * @exception NullPointerException
              * if the name is null.
              */

              public MyPrincipal(String userName) {
              super(userName);

              this.name = userName;
              //this.clientID = clientid;

              }

              /**
              * Return the Sample username for this SamplePrincipal.
              *
              *
              *
              * @return the Sample username for this SamplePrincipal
              */
              public String getName() {
              return name;
              }

              /**
              * Return a string representation of this SamplePrincipal.
              *
              *
              *
              * @return a string representation of this SamplePrincipal.
              */
              public String toString(){
              return ("MyPrincipal: " + name );

              }

              /**
              * Compares the specified Object with this SamplePrincipal
              * for equality. Returns true if the given object is also a
              * SamplePrincipal and the two SamplePrincipals have the same
              * username.
              *
              *
              *
              * @param o
              * Object to be compared for equality with this
              * SamplePrincipal.
              *
              * @return true if the specified Object is equal equal to this
              * SamplePrincipal.
              */
              public boolean equals(Object o) {
              if (o == null)
              return false;

              if (this == o)
              return true;

              if (!(o instanceof SimplePrincipal))
              return false;
              SimplePrincipal that = (SimplePrincipal) o;

              if (this.getName().equals(that.getName())
              && this.getName().equals(that.getName()))
              return true;
              return false;
              }

              /**
              * Return a hash code for this SamplePrincipal.
              *
              *
              *
              * @return a hash code for this SamplePrincipal.
              */
              public int hashCode() {
              return name.hashCode();
              }


              public String getLocale() {
              return locale;
              }

              public void setLocale(String locale) {
              this.locale = locale;
              }

              public TimeZone getTimeZone() {
              return timeZone;
              }

              public void setTimeZone(TimeZone timeSZone) {
              this.timeZone = timeSZone;
              }

              public String getUserPassword() {
              return userPassword;
              }

              public void setUserPassword(String userPassword) {
              this.userPassword = userPassword;
              }

              public String getUserName() {
              return userName;
              }

              public void setUserName(String userName) {
              this.userName = userName;
              }
              }
              ]







              [
              package com.coremetrics.sso.module;

              import java.security.MessageDigest;
              import java.security.NoSuchAlgorithmException;
              import java.security.Principal;
              import java.security.acl.Group;
              import java.sql.Connection;
              import java.sql.PreparedStatement;
              import java.sql.ResultSet;
              import java.sql.SQLException;
              import java.util.*;
              import java.io.IOException;
              import javax.security.auth.*;
              import javax.security.auth.callback.*;
              import javax.security.auth.login.*;
              import javax.security.auth.spi.*;
              import javax.security.jacc.PolicyContext;
              import javax.servlet.http.HttpServletRequest;

              import org.jboss.security.SecurityAssociation;
              import org.jboss.security.SimpleGroup;

              import org.jboss.security.auth.spi.AbstractServerLoginModule;

              import com.coremetrics.sharedservices.connection.SecureDBConnectionFactory;
              import com.coremetrics.sharedservices.exception.DBDownException;
              import com.coremetrics.sharedservices.exception.LoginDisallowedException;
              import com.coremetrics.sharedservices.exception.NoDBConfigException;
              import com.coremetrics.sharedservices.security.HTTPCodec;
              import com.coremetrics.sso.principal.MyPrincipal;


              public class DBLoginModule extends AbstractServerLoginModule {

              // initial state
              private Subject subject;

              private CallbackHandler callbackHandler;

              // configurable option
              private boolean debug = false;

              // the authentication status
              private boolean succeeded = false;

              private boolean commitSucceeded = false;

              private String principalId;

              private String clientid;

              private StringBuffer password;

              // private MyPrincipal userPrincipal;

              private String userEmail = null;

              private String userName = null;

              private TimeZone timeZone = null;

              private String homePageURL = null;

              private String clientName = null;

              private int verticalId;

              private Principal identity;

              private static final String USER_QUERY = "SELECT "
              +

              " SP.EMAIL_ADDRESS, SP.LOGIN_ENABLED, SP.PRINCIPAL_NAME, CSD.TIME_ZONE, CSD.HOME_PAGE_URL, C.CLIENT_NAME, C.VERTICAL_ID "
              + " FROM "
              + "SECURITY_PRINCIPALS SP, CLIENT_SETUP_DETAILS CSD,SECURITY_GROUP_ROLES SGR, SECURITY_ROLES SR, CLIENTS C "
              + " WHERE "
              + " SP.CLIENT_ID = ? AND SGR.group_id = SP.group_id AND SR.role_id = SGR.role_id AND SGR.client_id = SP.CLIENT_ID AND"
              + " CSD.client_id = SP.CLIENT_ID AND C.client_id = SP.CLIENT_ID AND PRINCIPAL_ID = ? AND SP.hpassword = ?";

              private static final String ROLE_QUERY = "select r.ROLE_ID, r.Role_Name "
              + "from Security_Group_Roles g, Security_Roles r, "
              + "Security_Principals p " + "where g.Role_ID = r.Role_ID "
              + "and g.Group_ID = p.Group_ID " + "and p.Principal_ID=? "
              + "and g.Client_ID = p.Client_ID " + "and p.Client_ID=?";

              public void initialize(Subject subject, CallbackHandler callbackHandler,
              Map sharedState, Map options) {

              super.initialize(subject, callbackHandler, sharedState, options);
              this.callbackHandler = callbackHandler;
              this.subject = subject;

              debug = "true".equalsIgnoreCase((String) options.get("debug"));
              }

              public DBLoginModule() {
              };

              public boolean login() throws LoginException {
              boolean isRequestFromLoginPage = false;
              super.login();
              super.loginOk = false;
              System.err.println("DBLoginModule login");

              System.err.println("1");

              if (callbackHandler == null) {

              System.out.println("Null callbackhandler throeing exception");
              throw new LoginException("Error: no CallbackHandler available "
              + "to garner authentication information from the user");
              }

              Callback[] callbacks = new Callback[2];
              callbacks[0] = new NameCallback("username");
              callbacks[1] = new PasswordCallback("password", false);

              try {
              callbackHandler.handle(callbacks);
              String dummy = (((NameCallback) callbacks[0]).getName());
              principalId = dummy.substring(8);
              clientid = dummy.substring(0, 8);

              try {
              HttpServletRequest request = (HttpServletRequest)PolicyContext.getContext("javax.servlet.http.HttpServletRequest");
              String isRequestFromLoginPageStr = request.getParameter("loginpage");
              if(isRequestFromLoginPageStr != null && isRequestFromLoginPageStr.equals("true")){
              isRequestFromLoginPage = true;
              }
              } catch (Exception e) {
              e.printStackTrace();
              }
              char[] tmpPassword = ((PasswordCallback) callbacks[1]).getPassword();
              if (tmpPassword == null) {
              tmpPassword = new char[0];
              }
              password = new StringBuffer();
              for (int i = 0; i < tmpPassword.length; i++) {
              password.append(tmpPassword);
              }

              ((PasswordCallback) callbacks[1]).clearPassword();

              try {
              String tempName = clientid + principalId;
              identity = createIdentity(tempName);
              if (identity instanceof MyPrincipal) {
              System.err.println("identity is of type MyPrincipal");
              } else {
              System.err.println("identity is of not type MyPrincipal");
              }
              } catch (Exception e) {
              System.err.println("Exception while making identiy " + e);
              }

              String tempName = "principalId+clientid";

              } catch (java.io.IOException io) {
              System.err.println("exception caught " + io);
              throw new LoginException(io.toString());
              } catch (UnsupportedCallbackException uc) {
              System.err.println("exception caught " + uc);
              throw new LoginException("Error: " + uc.getCallback().toString()
              + " not available to garner authentication information "
              + "from the user");
              }


              Connection conn = null;
              PreparedStatement ps = null;
              ResultSet rs = null;
              String hashPassword = null;
              System.err.println("before hash password");
              try {
              if(isRequestFromLoginPage){
              hashPassword = preparePassword(password.toString());
              }
              else{
              hashPassword = password.toString();
              }
              System.out.println("hashPassword " + hashPassword);
              } catch (Exception e) {
              throw new FailedLoginException("Failed to get hash password");
              }

              try {
              conn = SecureDBConnectionFactory.getConnection(Integer
              .parseInt(clientid), 0);
              if (conn == null) {
              System.err.println("Database connection is null ");
              throw new FailedLoginException(
              "Failed to get connection to client DB");
              }

              ps = conn.prepareStatement(USER_QUERY);
              ps.setInt(1, Integer.parseInt(clientid.trim()));
              ps.setString(2, principalId.trim());
              ps.setString(3, hashPassword.trim());
              rs = ps.executeQuery();

              if (!rs.next()) {
              System.err.println("No result found for this user ");
              throw new FailedLoginException("Failed to autheticate user ");
              } else {

              String loginAllowed = rs.getString(2);
              if (loginAllowed == null || !loginAllowed.equals("Y")) {
              System.err.println("login not allowed for this user");
              throw new LoginDisallowedException();
              }
              userEmail = rs.getString(1);
              ((MyPrincipal) identity).setUserEmail(userEmail);
              userName = rs.getString(3);
              ((MyPrincipal) identity).setUserName(userName);
              timeZone = TimeZone.getTimeZone(rs.getString(4));
              ((MyPrincipal) identity).setTimeZone(timeZone);
              homePageURL = rs.getString(5);
              ((MyPrincipal) identity).setHomePageURL(homePageURL);
              clientName = rs.getString(6);
              ((MyPrincipal) identity).setClientName(clientName);
              verticalId = rs.getInt(7);
              ((MyPrincipal) identity).setVerticalId(verticalId);
              }
              } catch (LoginDisallowedException ld) {
              System.out.println("Exception caught " + ld);
              throw new FailedLoginException("LoginDisallowedException");
              } catch (NoDBConfigException ndbe) {
              System.out.println("Exception caught " + ndbe);
              ndbe.printStackTrace();
              throw new FailedLoginException(
              "Failed to get connection configuration for client DB");
              } catch (DBDownException dbde) {
              System.out.println("Exception caught " + dbde);
              dbde.printStackTrace();
              throw new FailedLoginException("All DB Down Exception ");
              } catch (SQLException sq) {
              System.out.println("Exception caught " + sq);
              sq.printStackTrace();
              throw new FailedLoginException(
              "SQL Exception while authenticating user");
              } catch (Exception e) {
              System.out.println("Exception caught " + e);
              e.printStackTrace();
              throw new FailedLoginException(
              "Failed to get connection to client DB");
              } finally {
              System.err.println("Inside finally block");
              try {
              if (rs != null)
              rs.close();
              } catch (Exception e) {
              }
              try {
              if (ps != null)
              ps.close();
              } catch (Exception e) {
              }
              try {
              if (conn != null) {
              SecureDBConnectionFactory.safeConnectionClose(conn);

              }

              } catch (Exception e) {
              System.err.println("Exception caught " + e);
              }
              System.err.println("finally block done sucessfully");
              }

              succeeded = true;
              super.loginOk = true;
              super.log.trace("User '" + identity + "' authenticated, loginOk="
              + loginOk);
              SecurityAssociation.setPrincipal(identity);
              return true;

              }

              protected Principal getIdentity() {
              return identity;
              }

              protected Group[] getRoleSets() throws LoginException {
              Connection conn = null;
              ResultSet rs = null;
              PreparedStatement ps = null;
              HashMap setsMap = new HashMap();

              try {

              conn = SecureDBConnectionFactory.getConnection(Integer
              .parseInt(clientid), SecureDBConnectionFactory.GENERIC);
              // Get the users role names
              ps = conn.prepareStatement(ROLE_QUERY);
              ps.setString(1, principalId);
              ps.setString(2, clientid);
              rs = ps.executeQuery();
              if (!rs.next()) {
              throw new FailedLoginException(
              "No matching username found in Roles");
              } else {
              do {
              String name = rs.getString(1);
              // String groupName = rs.getString(2);
              // if( groupName == null || groupName.length() == 0 )
              String groupName = "Roles";
              Group group = (Group) setsMap.get(groupName);
              if (group == null) {
              group = new SimpleGroup(groupName);
              setsMap.put(groupName, group);
              }
              group.addMember(new MyPrincipal(name));
              } while (rs.next());

              }

              Group group = (Group) setsMap.get("Roles");
              if (group == null) {
              group = new SimpleGroup("Roles");
              setsMap.put("Roles", group);
              }
              group.addMember(new MyPrincipal("eluminate"));

              } catch (SQLException ex) {
              System.out.println("Exception caught while getRoleSets " + ex);
              ex.printStackTrace();
              throw new LoginException(ex.toString());
              } catch (DBDownException dbde) {
              throw new LoginException("DBDownException");
              } finally {
              if (ps != null) {
              try {
              ps.close();
              } catch (Exception ex) {
              }
              }
              if (rs != null) {
              try {
              rs.close();
              } catch (Exception ex) {
              }
              }
              try {
              SecureDBConnectionFactory.safeConnectionClose(conn);
              } catch (Exception e) {

              } finally {
              rs = null;
              ps = null;
              conn = null;
              }
              }

              Group[] roleSets = new Group[setsMap.size()];
              setsMap.values().toArray(roleSets);
              return roleSets;
              }


              private String preparePassword(String password)
              throws NoSuchAlgorithmException, IOException {
              System.out.println(password);
              MessageDigest md = MessageDigest.getInstance("MD5");
              md.update(password.getBytes());
              byte[] bytePass = md.digest();
              String encPass = HTTPCodec.encode(bytePass);
              return encPass;

              }


              }
              ]

              • 4. Re: Custom principal class
                soshah

                Nipun-

                Try to see if you can extend the UsernamePasswordLoginModule that Anil suggested that will let you hook in your custom Principal...


                or look at its code and see what its doing to hook in a custom Principal and perform that in your login module.


                Thanks
                Sohil