WildFly can't find database table in form-based authentication
rustlet Jan 29, 2016 11:11 AMHi All,
I've just started programming with Java EE and I'm trying to implement a simple web app that uses form-based user authentication with the JBoss database login module. When I run my web app and go to the home page it takes me to a login page. So far, so good. But when I submit the username and password the login fails with the following stack trace in server.log
...
2016-01-28 14:22:37,028 TRACE [org.jboss.security] (default task-5) PBOX00236: Begin initialize method
2016-01-28 14:22:37,028 DEBUG [org.jboss.security] (default task-5) PBOX00281: Password hashing activated, algorithm: SHA-256, encoding: base64, charset: null, callback: null, storeCallBack: null
2016-01-28 14:22:37,028 TRACE [org.jboss.security] (default task-5) PBOX00262: Module options [dsJndiName: java:/PostgresHibrid, principalsQuery: select passwd from users where username=?, rolesQuery: select role, 'Roles' from userroles where username=?, suspendResume: true]
2016-01-28 14:22:37,029 TRACE [org.jboss.security] (default task-5) PBOX00240: Begin login method
2016-01-28 14:22:37,030 TRACE [org.jboss.security] (default task-5) PBOX00263: Executing query select passwd from users where username=? with username user0
2016-01-28 14:22:37,037 TRACE [org.jboss.security] (default task-5) PBOX00244: Begin abort method, overall result: false
2016-01-28 14:22:37,037 DEBUG [org.jboss.security] (default task-5) PBOX00206: Login failure: javax.security.auth.login.LoginException: PBOX00065: Error processing query
at org.jboss.security.auth.spi.DatabaseServerLoginModule.getUsersPassword(DatabaseServerLoginModule.java:202)
at org.jboss.security.auth.spi.UsernamePasswordLoginModule.login(UsernamePasswordLoginModule.java:265)
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:498)
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 org.jboss.security.authentication.JBossCachedAuthenticationManager.defaultLogin(JBossCachedAuthenticationManager.java:406)
at org.jboss.security.authentication.JBossCachedAuthenticationManager.proceedWithJaasLogin(JBossCachedAuthenticationManager.java:345)
at org.jboss.security.authentication.JBossCachedAuthenticationManager.authenticate(JBossCachedAuthenticationManager.java:333)
at org.jboss.security.authentication.JBossCachedAuthenticationManager.isValid(JBossCachedAuthenticationManager.java:146)
at org.wildfly.extension.undertow.security.JAASIdentityManagerImpl.verifyCredential(JAASIdentityManagerImpl.java:111)
at org.wildfly.extension.undertow.security.JAASIdentityManagerImpl.verify(JAASIdentityManagerImpl.java:82)
at io.undertow.security.impl.FormAuthenticationMechanism.runFormAuth(FormAuthenticationMechanism.java:124)
at io.undertow.security.impl.FormAuthenticationMechanism.authenticate(FormAuthenticationMechanism.java:96)
at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:339)
at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:356)
at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.access$100(SecurityContextImpl.java:325)
at io.undertow.security.impl.SecurityContextImpl.attemptAuthentication(SecurityContextImpl.java:138)
at io.undertow.security.impl.SecurityContextImpl.authTransition(SecurityContextImpl.java:113)
at io.undertow.security.impl.SecurityContextImpl.authenticate(SecurityContextImpl.java:106)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:55)
at io.undertow.server.handlers.DisableCacheHandler.handleRequest(DisableCacheHandler.java:33)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AuthenticationConstraintHandler.handleRequest(AuthenticationConstraintHandler.java:51)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.servlet.handlers.security.ServletSecurityConstraintHandler.handleRequest(ServletSecurityConstraintHandler.java:56)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:72)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:282)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:261)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:80)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:172)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:199)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:774)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.postgresql.util.PSQLException: ERROR: relation "users" does not exist
Position: 20
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2182)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1911)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:173)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:622)
at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:472)
at org.postgresql.jdbc.PgStatement.executeQuery(PgStatement.java:386)
at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:504)
at org.jboss.security.auth.spi.DatabaseServerLoginModule.getUsersPassword(DatabaseServerLoginModule.java:185)
... 50 more
2016-01-28 14:22:37,038 TRACE [org.jboss.security] (default task-5) PBOX00201: End isValid, result = false
2016-01-28 14:22:37,040 TRACE [org.jboss.security] (default task-5) PBOX00354: Setting security roles ThreadLocal: null
...
It looks like the application can't find the table of users in the database. Any ideas as to what's causing this?
My configuration info follows. I'm using WildFly 9.0.2 Final and PostgreSQL 9.3. and I'm running on CentOS 6.
Setting up database in PostgreSQL
1) As user postgres
postgres=# create user hibrid with password 'hibrid';
postgres=# alter role hibrid with createdb;
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------+-----------
hibrid | Create DB | {}
postgres | Superuser, Create role, Create DB, Replication | {}
postgres=# create database hibrid owner hibrid;
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
hibrid | hibrid | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
2) As user hibrid
hibrid=> \c hibrid
hibrid=> CREATE TABLE users(username VARCHAR(255) PRIMARY KEY, passwd VARCHAR(255));
hibrid=> CREATE TABLE userroles(username VARCHAR(255), role VARCHAR(32));
hibrid=> \d
List of relations
Schema | Name | Type | Owner
--------+-----------+-------+--------
public | userroles | table | hibrid
public | users | table | hibrid
(2 rows)
hibrid=> INSERT INTO users (username, passwd) values ('user0', 'Eu9N7XpGSO2ujqTCad1XT9U4qGhfDFNvLz9+53qpSaM=');
hibrid=> select * from users;
username | passwd
----------+----------------------------------------------
user0 | Eu9N7XpGSO2ujqTCad1XT9U4qGhfDFNvLz9+53qpSaM=
(1 row)
hibrid=> INSERT INTO userroles (username, role) values ('user0', 'ADMIN');
hibrid=> select * from userroles;
username | role
----------+-------
user0 | ADMIN
(1 row)
Installing PostgreSQL JDBC driver in WildFly
1) Download the latest Postgres JDBC driver from https://jdbc.postgresql.org/download.html. We will assume the driver is downloaded to the directory /home/hibrid/bin and is named postgresql-9.4.1207.jar.
2) Start the WildFly CLI and connect to running WildFly instance
% ./jboss-cli.sh
[... /] connect
3) Install the module containing the JDBC driver.
[... /] module add --name=org.postgres --resources=/home/hibrid/bin/postgresql-9.4.1207.jar --dependencies=javax.api,javax.transaction.api
4) Install the JDBC Driver on the application server
[... /] /subsystem=datasources/jdbc-driver=postgres:add(driver-name="postgres",driver-module-name="org.postgres",driver-class-name=org.postgresql.Driver)
{"outcome" => "success"}
5) Datasource section of standalone-full.xml and standalone.xml now looks like this
<subsystem xmlns="urn:jboss:domain:datasources:3.0">
<datasources>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<datasource jndi-name="java:/PostgresHibrid" pool-name="PostgresHibrid" enabled="true">
<connection-url>jdbc:postgresql://localhost/postgres</connection-url>
<driver>postgres</driver>
<security>
<user-name>hibrid</user-name>
<password>hibrid</password>
</security>
</datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
<driver name="postgres" module="org.postgres">
<driver-class>org.postgresql.Driver</driver-class>
</driver>
</drivers>
</datasources>
</subsystem>
WebApp web.xml file
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
<security-constraint>
<web-resource-collection>
<web-resource-name>HtmlAuth</web-resource-name>
<description>application security constraints </description>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>ADMIN</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.xhtml</form-login-page>
<form-error-page>/error.xhtml</form-error-page>
</form-login-config>
</login-config>
<security-role>
<role-name>ADMIN</role-name>
</security-role>
</web-app>
WebApp jboss-web.xml file
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<security-domain>hibridDomain</security-domain>
</jboss-web>
Thanks for your help.