Skip to Content.
Sympa Menu

shibboleth-dev - RE: [Shib-Dev] Creating a Custom LoginHandler for Novel's eDirectory to handle Grace Logins/Expired Passwords

Subject: Shibboleth Developers

List archive

RE: [Shib-Dev] Creating a Custom LoginHandler for Novel's eDirectory to handle Grace Logins/Expired Passwords


Chronological Thread 
  • From: "Khanna, Sumit (khannast)" <>
  • To: "" <>
  • Subject: RE: [Shib-Dev] Creating a Custom LoginHandler for Novel's eDirectory to handle Grace Logins/Expired Passwords
  • Date: Thu, 28 Apr 2011 09:04:51 -0400
  • Accept-language: en-US
  • Acceptlanguage: en-US

I started looking at extending the UsernamePasswordLoginServlet like Brent suggested at first, but the solution of extending the BindAuthenticationHandler seems like a better solution as I can reuse the existing LDAP configuration.

 

To answer Daniel’s question, yes I’m trying to give the user a warning even after they’ve been fully authenticated. Novell’s e-Directory actually lets you bind successfully, even after your password expiration date, so long as you have grace logins left. So the call to super.authenticate() will still succeeded, meaning I need to move all that logic into the try block. I’m trying variations of the following:

 

 

public class GraceAuthenticationHandler extends BindAuthenticationHandler {

 

     

      protected final Log logger = LogFactory.getLog(this.getClass());

 

     

      public GraceAuthenticationHandler() {

      }

 

      public GraceAuthenticationHandler(final AuthenticatorConfig ac) {

            this.setAuthenticatorConfig(ac);

      }

 

      public void authenticate(final ConnectionHandler ch, final AuthenticationCriteria ac) throws NamingException {

 

            Ldap ldap = null;

           

            try {

                  super.authenticate(ch, ac);

 

                        ldap = new Ldap(ch.getLdapConfig());

                       

                        Attributes attrs = ldap.getAttributes(ac.getDn(), new String[] { "passwordExpirationTime", "loginGraceRemaining" } );

                        String exp = attrs.get("passwordExpirationTime") != null ? (String) attrs.get("passwordExpirationTime").get() : "";

                        String graceLogins = attrs.get("loginGraceRemaining") != null ? (String) attrs.get("loginGraceRemaining").get() : "";

 

                        logger.debug( "DN " + ac.getDn() + " - Exp: "+exp+" - Grace: " + graceLogins );

                       

                       

                        Date date;

                        try {

                              date = new SimpleDateFormat("yyyyMMddHHmmss").parse(exp);

                        }

                        catch (ParseException p) {

                              throw (AuthenticationException) new GraceLoginAuthenticationException("User's password expiration time is in incorrect format",null,"");

                              //throw new AuthenticationException("User's password expiration time is in incorrect format");

                        }

                       

                        if(date.before(new Date())) {

                              throw (AuthenticationException) new GraceLoginAuthenticationException("Password has expired",date,graceLogins);

                              //throw new AuthenticationException("Password has expired");

                        }

 

            } catch(RuntimeException e) {

                  throw e;

            } finally {

                  if (ldap != null) {

                        ldap.close();

                  }

            }

      }

 

 

  public GraceAuthenticationHandler newInstance()

  {

    return new GraceAuthenticationHandler(this.config);

  }

}

 

 

But I have a couple of use. First, is my logger setup correctly? I’m not actually seeing that line in the idp-process or tomcat logs.

 

Second, how is that exception transferred over to the login servlet? I see my edu.uc.ucit.shibboleth.idm.auth.GraceLoginAuthenticationException in to logs (which is just an AuthenticationException with some added fields), but in the jsp page when you do a request.getAttribute(LoginHandler.AUTHENTICATION_EXCEPTION_KEY), the type of that class is actually a javax.security.auth.login.LoginException. Does it just copy the message from that exception into the message of a new one?

 

Finally, and this is the big one, attrs.get("passwordExpirationTime") returns a null. You can see I tried changing new Ldap(this.config) to new Ldap(ch.getLdapConfig()), but in both cases, I don’t get any vales. If print out the DN, it is correct (cn=username,ou=People,o=uc). I’m not getting any connection exceptions and the user in the login.conf does have permission to view that attribute for a user. I’m sure I’m just missing something simple. Any ideas?

 

Sumit Khanna

 

 

From: [mailto:] On Behalf Of Daniel Fisher
Sent: Tuesday, April 26, 2011 9:36 PM
To:
Subject: Re: [Shib-Dev] Creating a Custom LoginHandler for Novel's eDirectory to handle Grace Logins/Expired Passwords

 

I'm a little confused by your example because the user won't get any messages until the account is locked. Are you trying to tell the user when their account expires/logins left even though the user successfully authenticated? I believe that needs to be done in an out-of-band process, not during authentication. See more below.

 

On Tue, Apr 26, 2011 at 3:57 PM, Khanna, Sumit (khannast) <> wrote:

 

The Handler looks very basic. Even looking at the AbstractHandler, I don’t entirely understand how the username/password is passed to the JAAS provider, but it seems I was looking in the wrong place to do this type of expired password check anyway. I’d want to do it during the point where the bind actually occurs so I can read LDAP attributes and throw custom exceptions. So next I looked at the VT middleware JAAS provider:

 

http://code.google.com/p/vt-middleware/source/browse/vt-ldap/trunk/src/main/java/edu/vt/middleware/ldap/jaas/LdapLoginModule.java

 

FYI, you're looking at trunk. Latest IDP is using version 3.3.2.

I'll echo Brent's concerns about putting this logic in the authentication layer, but one way to do it is to implement your own AuthenticationHandler:

 

public class GraceAuthenticationHandler extends BindAuthenticationHandler

{

 

  public GraceAuthenticationHandler() {}

 

 

  public GraceAuthenticationHandler(final AuthenticatorConfig ac) 

  {

    this.setAuthenticatorConfig(ac);

  }

 

  public void authenticate(

    final ConnectionHandler ch, 

    final AuthenticationCriteria ac) 

    throws NamingException

  {

    try {

      super.authenticate(ch, ac);

    } catch (AuthenticationException e) {

      Ldap ldap = null;

      try {

        ldap = new Ldap(this.config);

        Attributes a = ldap.getAttributes(

          ac.getDn(),

          new String[]{"passwordExpirationTime", "loginGraceRemaining"});

        String pet = a.get("passwordExpirationTime") != null ?

          (String) a.get("passwordExpirationTime").get() : ""; 

        String lgr = a.get("loginGraceRemaining") != null ?

          (String) a.get("loginGraceRemaining").get() : ""; 

        throw new AuthenticationException(

          String.format(

            "Password Expiration Time: %s. Login Grace Remaining: %s.", pet, lgr));

      } finally {

        if (ldap != null) {

          ldap.close();

        }   

      }   

    }   

  }

 

 

  public GraceAuthenticationHandler newInstance()

  {

    return new GraceAuthenticationHandler(this.config);

  }

}

 

Edit your login.config and add the option: authenticationHandler="edu.uc.mypackage.GraceAuthenticationHandler"

Now you can handle the exception in the JSP and give the user the message.

 

 

This actually confused me even more, because I remember when I was originally setting up and configuring Shibboleth, that I had trouble with the login.config and it looked like, in the log file, that the items in the login.conf were actually calling get() and set() methods within the LdapLoginModule class (similar to how properties are set using Spring). However in the LdapLoginModule, I don’t see those getters or setters for things like host, base, bindDn, etc, nor do I see them in the base class.

 

They are set via reflection on the Authenticator class, the login module doesn't contain those properties..

 

--Daniel Fisher

 




Archive powered by MHonArc 2.6.16.

Top of Page