I’m trying to get build a simple Active Directory tools that allows me to authentify with Kerberos.
While testing I landed on a problem which is quite annoying! If I put invalid values in the fields and submit ( users that doesn’t exist in the AD or a bad user/password combination ) I get a LoginException (Javadoc). If I could catch that and automatically say that the login failed due to a wrong input, that would be good.
The problem is that if I have a problem connecting to the Active Directory, or if the request timeout, I get the same exception. If I print the trace I can see the different message but the exception type is the same…
Do you know if I do something wrong or if I could catch something different to make it work. I already tried to catch the subclass LoginFailedException but it didn’t work, it went directly into the LoginException(Javadoc) task.
Here is the trace for the two problem in the order :
Wrong username/Password
javax.security.auth.login.LoginException: Pre-authentication information was invalid (24)
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Unknown Source)
at com.sun.security.auth.module.Krb5LoginModule.login(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at javax.security.auth.login.LoginContext.invoke(Unknown Source)
at javax.security.auth.login.LoginContext.access$000(Unknown Source)
at javax.security.auth.login.LoginContext$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(Unknown Source)
at javax.security.auth.login.LoginContext.login(Unknown Source)
at com.banctecmtl.ca.vlp.tools.ActiveDirectoryValidator.validateUser(ActiveDirectoryValidator.java:80)
at com.banctecmtl.ca.vlp.controller.UserAccessController.authentify(UserAccessController.java:161)
at com.banctecmtl.ca.vlp.view.webview.server.UserAccessServiceImpl.authenticate(UserAccessServiceImpl.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:569)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:208)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248)
at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:362)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.handler.RequestLogHandler.handle(RequestLogHandler.java:49)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:647)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
Caused by: KrbException: Pre-authentication information was invalid (24)
at sun.security.krb5.KrbAsRep.<init>(Unknown Source)
at sun.security.krb5.KrbAsReq.getReply(Unknown Source)
at sun.security.krb5.Credentials.sendASRequest(Unknown Source)
at sun.security.krb5.Credentials.acquireTGT(Unknown Source)
... 42 more
Caused by: KrbException: Identifier doesn't match expected value (906)
at sun.security.krb5.internal.KDCRep.init(Unknown Source)
at sun.security.krb5.internal.ASRep.init(Unknown Source)
at sun.security.krb5.internal.ASRep.<init>(Unknown Source)
... 46 more
Active directory unreachable (disabled the network card :P)
javax.security.auth.login.LoginException: ADNAMEHERE.LAN
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Unknown Source)
at com.sun.security.auth.module.Krb5LoginModule.login(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at javax.security.auth.login.LoginContext.invoke(Unknown Source)
at javax.security.auth.login.LoginContext.access$000(Unknown Source)
at javax.security.auth.login.LoginContext$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(Unknown Source)
at javax.security.auth.login.LoginContext.login(Unknown Source)
at com.banctecmtl.ca.vlp.tools.ActiveDirectoryValidator.validateUser(ActiveDirectoryValidator.java:80)
at com.banctecmtl.ca.vlp.controller.UserAccessController.authentify(UserAccessController.java:161)
at com.banctecmtl.ca.vlp.view.webview.server.UserAccessServiceImpl.authenticate(UserAccessServiceImpl.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:569)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:208)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248)
at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:362)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.handler.RequestLogHandler.handle(RequestLogHandler.java:49)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:647)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
Caused by: java.net.UnknownHostException: ADNAMEHERE.LAN
at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
at java.net.InetAddress$1.lookupAllHostAddr(Unknown Source)
at java.net.InetAddress.getAddressFromNameService(Unknown Source)
at java.net.InetAddress.getAllByName0(Unknown Source)
at java.net.InetAddress.getAllByName(Unknown Source)
at java.net.InetAddress.getAllByName(Unknown Source)
at java.net.InetAddress.getByName(Unknown Source)
at sun.security.krb5.internal.UDPClient.<init>(Unknown Source)
at sun.security.krb5.KrbKdcReq$KdcCommunication.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.krb5.KrbKdcReq.send(Unknown Source)
at sun.security.krb5.KrbKdcReq.send(Unknown Source)
at sun.security.krb5.KrbKdcReq.send(Unknown Source)
at sun.security.krb5.KrbAsReq.send(Unknown Source)
at sun.security.krb5.Credentials.sendASRequest(Unknown Source)
at sun.security.krb5.Credentials.acquireTGT(Unknown Source)
... 42 more
Thanks a lot!
You can discriminate the cause of the issue thanks to
LoginException.getCause(). If that exception is available, it may beIOExceptionorKrbException.I use this good example as a test case and add the following exception handling:
In that context,
KrbExceptioncannot discriminate an invalid username and password from an invalid Kerberos client configuration, inkrb5.confor any other parameters like an misspelled realm.But thanks to
IOException, you are sure about an ActiveDirectory server unavailability, except if DNS name or IP address is wrong in settings.So if your setup is correct and works for at least one user, you will get an
IOExceptionasLoginExceptioncause when ActiveDirectory is not available, and aKrbExceptionfor any authentication issue like unknown username or invalid password.By the way, I agree with you that the exception handling is rough, probably because Kerberos stack implementation itself only throws
KrbExceptionwithout more details.If that first option does not provide enough details with existing code, you should create your own LoginModule inherited from
com.sun.security.auth.module.Krb5LoginModuleto raise different exception according to the root cause. I invite you to read the latest OpenJDK source code of Krb5LoginModule.