Announcement Announcement Module
Collapse
No announcement yet.
Authenticate with AuthenticationException Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Authenticate with AuthenticationException

    The ldaptemplate.authenticate is working great, but QA won't let me proceed without the AuthenticationException.

    I realize that the AuthenticationException is logged, but I need to return this information to the caller so that they can seek remedy.

    For example, if error is:
    52e then user will know to re-enter password
    530 then user will know to try later
    532 then user will know password has expired
    533 then user will know that account is disabled

    etc....

    If I have to use "plain old" JNDI for authentication purposes just to capture the AuthenticationException, then SPRING LDAP is useless to me.

    Please make the ldaptemplate.authenticate throwable or somehow able to return the exception message instead of just FALSE.

    Thanks!
    -Larry
    Last edited by lyates; Jul 22nd, 2009, 08:15 PM.

  • #2
    Temporary fix for Authenticate with AuthenticationException

    OK.

    So I added one additional "authenticate" method in LdapOperations.java and LdapTemplate.java named "authenticate" which "throws Exception" only if it is an AuthenticationException otherwise the exception is logged and the method returns false (like it does now).

    I modified my source application to catch the Exception.

    I threw the two source files ( LdapOperations.java and LdapTemplate.java ) in the same src/ directory where my application source files live and used ant to compile.

    Success!

    Thank goodness for open source

    Maybe one day, we'll have official "authenticate" methods that throws the AuthenticationException rather than simply returning false.

    There are probably several other ways to accomplish this, but this worked for me...

    This I added to LdapTemplate:
    Code:
    	public boolean authenticate(Name base, String filter, String password,
    			final AuthenticatedLdapEntryContextCallback callback) throws Exception {
    
    		List result = search(base, filter, new LdapEntryIdentificationContextMapper());
    		if (result.size() > 1) {
    			log.error("Unable to find unique entry matching in authentication; base: '" + base + "'; filter: '"
    					+ filter + "'. Found " + result.size() + " matching entries");
    			return false;
    		}
    
    		final LdapEntryIdentification entryIdentification = (LdapEntryIdentification) result.get(0);
    
    		try {
    			DirContext ctx = contextSource.getContext(entryIdentification.getAbsoluteDn().toString(), password);
    			executeWithContext(new ContextExecutor() {
    				public Object executeWithContext(DirContext ctx) throws javax.naming.NamingException {
    					callback.executeWithContext(ctx, entryIdentification);
    					return null;
    				}
    			}, ctx);
    			return true;
    		}
    		catch (AuthenticationException e) {
    			throw e;
    		}
    		catch (Exception e) {
    			log.error("Authentication failed for entry with DN '" + entryIdentification.getAbsoluteDn() + "'Error is:", e);
    			return false;
    		}
    	}
    Thanks!
    -Larry
    Last edited by lyates; Jul 23rd, 2009, 09:04 AM.

    Comment


    • #3
      Barking up the wrong tree?

      When I applied this patch, I was very new to the entire Spring concept.

      Is there another way to obtain the reason for the AuthenticationException?

      I really need those error codes.
      Are they mapped elsewhere?

      As this project nears deployment, I don't like the idea of including "patched" Spring LDAP code with it.

      Thanks!
      -Larry

      Comment


      • #4
        Let me present one possible solution to your problem. Let's say that there is a callback interface like:

        Code:
        public interface AuthenticationErrorCallback {
            /**
             * This method will be called with the authentication exception in
             * case there is a problem with the authentication.
             *
             * @param e the exception that was caught in the authentication method
             */
            void execute(Exception e);
        }
        Let's further assume that the authentication methods in LdapTemplate call this callback when there is an error:

        Code:
           boolean authenticate(String base, String filter, String password,
              AuthenticatedLdapEntryContextCallback callback,
              AuthenticationErrorCallback errorCallback)
           {
              ...
              }
              catch (Exception e) {
                 log.error("Authentication failed for entry with DN '" + entryIdentification.getAbsoluteDn() + "'", e);
                 errorCallback.execute(e);
                 return false;
              }
           }
        A user interested in the actual exception could then write a callback that collects the exception for later retrieval, like this:

        Code:
        public static final class CollectingErrorCallback implements AuthenticationErrorCallback {
           private Exception error;
           public void execute(Exception e) {
              this.error = e;
           }
           public Exception getError() {
              return error;
           }
        }
        When we put these pieces together, it could look like this:

        Code:
           CollectingErrorCallback errorCallback = new CollectingErrorCallback();
           AuthenticatedLdapEntryContextCallback callback = new NullAuthenticatedLdapEntryContextCallback();
           boolean result = tested.authenticate("", filter.toString(), "invalidpassword", callback, errorCallback);
           if (!result) {
              Exception error = errorCallback.getError();
              // error is likely of type org.springframework.ldap.AuthenticationException
           }
        We would obviously provide the CollectingErrorCallback implementation. We would also make NullAuthenticatedLdapEntryContextCallback public, which it isn't today. So the only code you need to write is the last section above.

        Would this be of any help to you?

        Comment


        • #5
          This looks like a perfect solution!

          Originally posted by ulsa View Post
          We would obviously provide the CollectingErrorCallback implementation. We would also make NullAuthenticatedLdapEntryContextCallback public, which it isn't today. So the only code you need to write is the last section above.

          Would this be of any help to you?
          Ulsa,
          This is really beautiful code!

          It supplies both 'true' or 'false' AND if the user wants it, the user can ALSO have access to the AuthenticationException.

          Yes. Yes. Yes!
          This looks like a perfect solution...

          Thanks!
          -Larry

          Comment


          • #6
            Yes. Yes. Yes!
            This looks like a perfect solution...
            Good. I'll commit it in a while.

            I haven't heard from Mattias yet. He might very well come up with a better solution, but I guess we can go with this for now.

            Comment


            • #7
              Woo Hoo!

              Originally posted by ulsa View Post
              Good. I'll commit it in a while.

              I haven't heard from Mattias yet. He might very well come up with a better solution, but I guess we can go with this for now.
              I will implement this as soon as it's ready.

              Will it be available as a "1.3.x nightly snapshot"?

              Comment


              • #8
                Yes, it will be available as a nightly snapshot. We've hit a max file listing limit in S3 again, so the latest snapshots are not visible. It will be fixed soon, and then tomorrow's nightly should contain the code.

                Comment


                • #9
                  Ulsa,

                  THANK YOU VERY MUCH!
                  -Larry

                  Comment

                  Working...
                  X