Reputation: 43
Ok so I have spent a good amount of time on this but, it would appear that everything is set correctly and there is a bug in the com.sun.enterprise.security.ee.auth.realm.jdbc.JDBCRealm code.
I am attempting to use form based authentication with programmatic log in. I am using Glassfish 4 and JDK 1.8_40. When I enter my details into the login page the container attempts to direct me to the secured resource however it gives me a access denied at the same URL. Upon investigating this I have discovered that although the login succeeded the container failed to validate my login and has failed to associate the principle with any roles. This causing the access denied error. In order to discover what was going on I set the logging on glass fish to fine and discovered the array index out of bounds error seen in the stack trace.
[2015-03-25T16:19:43.088+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security.auth.realm] [tid: _ThreadID=59 _ThreadName=http-listener-1(4)] [timeMillis: 1427296783088] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.ee.auth.realm.jdbc.JDBCRealm] [METHODNAME: isUserValid] [[
Cannot validate user
java.lang.ArrayIndexOutOfBoundsException: 64
at com.sun.enterprise.security.ee.auth.realm.jdbc.JDBCRealm.isUserValid(JDBCRealm.java:430)
at com.sun.enterprise.security.ee.auth.realm.jdbc.JDBCRealm.authenticate(JDBCRealm.java:324)
at com.sun.enterprise.security.ee.auth.login.JDBCLoginModule.authenticate(JDBCLoginModule.java:78)
at com.sun.enterprise.security.auth.login.PasswordLoginModule.authenticateUser(PasswordLoginModule.java:116)
at com.sun.enterprise.security.BasePasswordLoginModule.login(BasePasswordLoginModule.java:146)
at sun.reflect.GeneratedMethodAccessor78.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:755)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:195)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:682)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:680)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
at javax.security.auth.login.LoginContext.login(LoginContext.java:587)
at com.sun.enterprise.security.auth.login.LoginContextDriver.doPasswordLogin(LoginContextDriver.java:383)
at com.sun.enterprise.security.auth.login.LoginContextDriver.login(LoginContextDriver.java:241)
at com.sun.enterprise.security.auth.login.LoginContextDriver.login(LoginContextDriver.java:154)
at com.sun.web.security.RealmAdapter.authenticate(RealmAdapter.java:695)
at com.sun.web.security.RealmAdapter.authenticate(RealmAdapter.java:636)
at org.apache.catalina.authenticator.AuthenticatorBase.doLogin(AuthenticatorBase.java:957)
at org.apache.catalina.authenticator.AuthenticatorBase.login(AuthenticatorBase.java:939)
at org.apache.catalina.connector.Request.login(Request.java:2245)
at org.apache.catalina.connector.Request.login(Request.java:2224)
at org.apache.catalina.connector.RequestFacade.login(RequestFacade.java:1113)
at com.merrimansa.beans.UserAuthBean.login(UserAuthBean.java:80)
at com.merrimansa.beans.UserAuthBean$Proxy$_$$_WeldClientProxy.login(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at javax.el.ELUtil.invokeMethod(ELUtil.java:326)
at javax.el.BeanELResolver.invoke(BeanELResolver.java:536)
at javax.el.CompositeELResolver.invoke(CompositeELResolver.java:256)
at com.sun.el.parser.AstValue.invoke(AstValue.java:269)
at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304)
at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:147)
at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:818)
at javax.faces.component.UICommand.broadcast(UICommand.java:300)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
at java.lang.Thread.run(Thread.java:745)
]]
[2015-03-25T16:19:43.150+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security] [tid: _ThreadID=33 _ThreadName=admin-listener(2)] [timeMillis: 1427296783150] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.web.integration.WebSecurityManager] [METHODNAME: setPolicyContext] [[
[Web-Security] Policy Context ID was: __admingui/__admingui]]
[2015-03-25T16:19:43.151+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security] [tid: _ThreadID=33 _ThreadName=admin-listener(2)] [timeMillis: 1427296783151] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.web.integration.WebSecurityManager] [METHODNAME: checkPermissionWithoutCache] [[
[Web-Security] Codesource with Web URL: file:/__admingui/__admingui]]
[2015-03-25T16:19:43.151+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security] [tid: _ThreadID=33 _ThreadName=admin-listener(2)] [timeMillis: 1427296783151] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.web.integration.WebSecurityManager] [METHODNAME: checkPermissionWithoutCache] [[
[Web-Security] Checking Web Permission with Principals : null]]
[2015-03-25T16:19:43.151+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security] [tid: _ThreadID=33 _ThreadName=admin-listener(2)] [timeMillis: 1427296783151] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.web.integration.WebSecurityManager] [METHODNAME: checkPermissionWithoutCache] [[
[Web-Security] Web Permission = ("javax.security.jacc.WebResourcePermission" "/download/log/" "GET")]]
[2015-03-25T16:19:43.151+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security.jmac.config] [tid: _ThreadID=33 _ThreadName=admin-listener(2)] [timeMillis: 1427296783151] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.jmac.config.GFServerConfigProvider] [METHODNAME: getEntry] [[
getEntry for: HttpServlet -- GFConsoleAuthModule
module class: org.glassfish.admingui.common.security.AdminConsoleAuthModule
options: {loginErrorPage=/loginError.jsf, loginPage=/login.jsf}
request policy: javax.security.auth.message.MessagePolicy@7a09d92
response policy: null]]
[2015-03-25T16:19:43.182+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security.auth.realm] [tid: _ThreadID=252 _ThreadName=admin-listener(9)] [timeMillis: 1427296783182] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.auth.realm.file.FileRealm] [METHODNAME: init] [[
FileRealm : file=/etc/Glassfish4/glassfish4/glassfish/domains/domain1/config/admin-keyfile]]
[2015-03-25T16:19:43.182+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security.auth.realm] [tid: _ThreadID=252 _ThreadName=admin-listener(9)] [timeMillis: 1427296783182] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.auth.realm.file.FileRealm] [METHODNAME: init] [[
FileRealm : jaas-context=ignore]]
[2015-03-25T16:19:43.184+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security] [tid: _ThreadID=252 _ThreadName=admin-listener(9)] [timeMillis: 1427296783184] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.BasePasswordLoginModule] [METHODNAME: initialize] [[
Login module initialized: class com.sun.enterprise.security.auth.login.FileLoginModule]]
[2015-03-25T16:19:43.184+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security] [tid: _ThreadID=252 _ThreadName=admin-listener(9)] [timeMillis: 1427296783184] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.BasePasswordLoginModule] [METHODNAME: abort] [[
JAAS authentication aborted.]]
[2015-03-25T16:19:43.197+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security] [tid: _ThreadID=59 _ThreadName=http-listener-1(4)] [timeMillis: 1427296783197] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.BasePasswordLoginModule] [METHODNAME: login] [[
JAAS login complete.]]
[2015-03-25T16:19:43.197+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security] [tid: _ThreadID=59 _ThreadName=http-listener-1(4)] [timeMillis: 1427296783197] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.BasePasswordLoginModule] [METHODNAME: commit] [[
JAAS authentication committed.]]
[2015-03-25T16:19:43.198+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security.auth.login] [tid: _ThreadID=59 _ThreadName=http-listener-1(4)] [timeMillis: 1427296783198] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.auth.login.LoginContextDriver] [METHODNAME: doPasswordLogin] [[
Password login succeeded for : [email protected]]]
[2015-03-25T16:19:43.207+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security.auth.login] [tid: _ThreadID=59 _ThreadName=http-listener-1(4)] [timeMillis: 1427296783207] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.auth.login.LoginContextDriver] [METHODNAME: doPasswordLogin] [[
Set security context as user: [email protected]]]
[2015-03-25T16:19:43.467+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security] [tid: _ThreadID=56 _ThreadName=http-listener-1(1)] [timeMillis: 1427296783467] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.web.integration.WebSecurityManager] [METHODNAME: setPolicyContext] [[
[Web-Security] Setting Policy Context ID: old = null ctxID = HSEManagmentApp/HSEManagmentApp]]
I then investigated the source code for the method in question and discovered a comment saying it could accept a maximum length of 50 see code below. I'm not sure if this is a red herring or if I have just set something wrong in my JDBC realm. Any help on this would be much appreciated as it is eating up my time and I'm no closer to a solution.
private boolean isUserValid(String user, char[] password) {
401 Connection connection = null;
402 PreparedStatement statement = null;
403 ResultSet rs = null;
404 boolean valid = false;
405
406 try {
407 char[] hpwd = hashPassword(password);
408 connection = getConnection();
409 statement = connection.prepareStatement(passwordQuery);
410 statement.setString(1, user);
411 rs = statement.executeQuery();
412 if (rs.next()) {
413 //Obtain the password as a char[] with a max size of 50
414 Reader reader = rs.getCharacterStream(1);
415 char[] pwd = new char[1024];
416 int noOfChars = reader.read(pwd);
417
418 /*Since pwd contains 1024 elements arbitrarily initialized,
419 construct a new char[] that has the right no of char elements
420 to be used for equal comparison*/
421 if (noOfChars < 0) {
422 noOfChars = 0;
423 }
424 char[] passwd = new char[noOfChars];
425 System.arraycopy(pwd, 0, passwd, 0, noOfChars);
426 if (HEX.equalsIgnoreCase(getProperty(PARAM_ENCODING))) {
427 valid = true;
428 //Do a case-insensitive equals
429 for(int i = 0; i < noOfChars; i ++) {
430 if (!(Character.toLowerCase(passwd[i]) == Character.toLowerCase(hpwd[i]))) {
431 valid = false;
432 break;
433 }
434 }
435 } else {
436 valid = Arrays.equals(passwd, hpwd);
437 }
438 }
439 } catch(SQLException ex) {
440 _logger.log(Level.SEVERE, "jdbcrealm.invaliduserreason",
441 new String [] {user,ex.toString()});
442 if (_logger.isLoggable(Level.FINE)) {
443 _logger.log(Level.FINE, "Cannot validate user", ex);
444 }
445 } catch(Exception ex) {
446 _logger.log(Level.SEVERE, "jdbcrealm.invaliduser", user);
447 if (_logger.isLoggable(Level.FINE)) {
448 _logger.log(Level.FINE, "Cannot validate user", ex);
449 }
450 } finally {
451 close(connection, statement, rs);
452 }
453 return valid;
454 }
I have attached my realm file in case it is something silly but I have tried just about every combination. I have also checked my hashing in the database and it is correct. Only odd thing is if I set hashing to 'none' then it doesn't work at all.
Upvotes: 0
Views: 1270
Reputation: 43
Ok I have solved this issue and all the others I was having with authentication and wanted to post an answer for future people facing this problem. It seems that the SQL queries being used are filling in any unused space in the database field with white space so; as I had my password field set to nvarchar(500) that was the length of the password that was being returned although all characters after 64 were white space. This also caused an issue with role to group mapping, as this is a various length field I cant change the field length to compensate so must now look for the problem with the driver or queries involved.
Regards
Upvotes: 1