Debugging Badge Authentication Failures

I am trying to enable badge support on one of our IdPs connected to an AD/DB Hybrid user source. I added the query to the badge query of the User source config and confirmed that the query returns the username as expected.

Then I attempt to perform the badge scan in a login and all I get is “badge scan failed”. Looking at the logs, the correct badge number is coming across to the GW, however it fails the auth. Is there any other loggers that can be enabled to debug this further? I cant seem to trace anymore as to what might be failing…

It looks like your AD/DB Hybrid user source has a failover source - do your badges live in the DB pointed to by your primary AD/DB hybrid user source? If so, setting logger UserSource.AD_DB_Hybrid to trace might give some more info. I’ve also seen setups where a soft failover user source is configured and the failover contains the badges, so if a badge is used, the primary would fail, but the failover source would succeed. In that case, I can give you a log name to set to trace if you give me the failover source type that is being used.

You may also want to double check that there is no extra whitespace given with the badge during authentication and what is stored in the DB. Also double check that more than one user does not share a badge in the DB (authentication fails in this case since the result is ambiguous).

You might also want to hit the + icon next to the third row in your log screenshot to see what the full stack trace tells you regarding why primary authentication failed.

I do have a backup source. It was set to HARD fail, but did not need it for this user source right now so disabled it for the sake of ease. The badge data lives in the DB, the same as the rest of the user/role data.

The badge reader I have is a pcProx from RFIdeas, fairly common that I know of. It is sending an Enter character after the badge scan. (FYI this is on WIndows / Chrome 85)

The badge query is returning a single row, single column, “username” (same as the example in the help text on the user source config page)

Here is the trace from the auth error but it doesn’t make much sense because the user source works fine, we have been using it for years, only config change was to populate the badge query. All the roles show fine when editing the user source.

java.lang.Exception: Error while loading roles from database.
at com.inductiveautomation.ignition.gateway.authentication.impl.ADtoDBHybridAuthenticator.authenticateBadge(ADtoDBHybridAuthenticator.java:216)
at com.inductiveautomation.ignition.gateway.authentication.impl.ADtoDBHybridAuthenticator.authenticateAD(ADtoDBHybridAuthenticator.java:234)
at com.inductiveautomation.ignition.gateway.authentication.impl.SsoHelper.authenticate(SsoHelper.java:39)
at com.inductiveautomation.ignition.gateway.authentication.impl.ADtoDBHybridAuthenticator.authenticate(ADtoDBHybridAuthenticator.java:108)
at com.inductiveautomation.ignition.gateway.authentication.UserSourceWrapper.authenticate(UserSourceWrapper.java:275)
at com.inductiveautomation.ignition.gateway.auth.authn.routes.AuthenticationRoutes$Authenticator.authenticate(AuthenticationRoutes.java:202)
at com.inductiveautomation.ignition.gateway.auth.authn.routes.AuthenticationRoutes$Authenticator.handle(AuthenticationRoutes.java:278)
at com.inductiveautomation.ignition.gateway.dataroutes.Route.service(Route.java:252)
at com.inductiveautomation.ignition.gateway.dataroutes.RouteGroupImpl.service(RouteGroupImpl.java:61)
at com.inductiveautomation.ignition.gateway.dataroutes.RouteGroupServlet.serviceInternal(RouteGroupServlet.java:35)
at com.inductiveautomation.ignition.gateway.dataroutes.AbstractRouteGroupServlet.service(AbstractRouteGroupServlet.java:38)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder$NotAsyncServlet.service(ServletHolder.java:1391)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:760)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:547)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:590)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1607)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1297)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:485)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1577)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1212)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:59)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
at org.eclipse.jetty.rewrite.handler.RewriteHandler.handle(RewriteHandler.java:322)
at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:59)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:146)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
at org.eclipse.jetty.server.Server.handle(Server.java:500)
at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:383)
at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:547)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:270)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onFillable(SslConnection.java:543)
at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:398)
at org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:161)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:388)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The server principal "CamstarViewer" is not able to access the database "Ignition" under the current security context.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:258)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1535)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:467)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:409)
at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7151)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2478)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:219)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:199)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:331)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:122)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:122)
at com.inductiveautomation.ignition.gateway.datasource.SRConnectionWrapper$SRPreparedStatement.executeQuery(SRConnectionWrapper.java:1008)
at com.inductiveautomation.ignition.gateway.datasource.SRConnectionWrapper.runPrepQuery(SRConnectionWrapper.java:169)
at com.inductiveautomation.ignition.gateway.authentication.impl.ADtoDBHybridAuthenticator.authenticateBadge(ADtoDBHybridAuthenticator.java:175)
... 53 common frames omitted


I'm no SQL Server expert, but that exception leads me to believe that there is some kind of permissions issue at play here. In your initial post, you mentioned:

I added the query to the badge query of the User source config and confirmed that the query returns the username as expected.

How did you confirm that the query returns the expected username? Did you use a tool outside of Ignition to verify? And did you use the same credentials that Ignition uses in the datasource connection configuration? Could there also be some kind of access control based on IP address which could be causing issues here? Also, is there something in your badge query that deviates from the other queries? For example, if you use some new table distinct from any of the other queries maybe the credentials used by Ignition needs access granted to that table?

ARGH! Now I feel embarrassed. We have 2 DB connections with very similar names but different access rights. All the rest of the user source queries work under both connections except for the badge, so a regular login worked but not badge. I switched the user source to the other DB connection and now all is well. The config is right in our other gateways, but this one happened to have a wrong config!

Thanks for the help!

1 Like