MS Azure IDP Help

Setting up my first non Ignition IDP for a project.

The customer is using the Azure SAML IDP.

Ignition version is 8.1.7

We have everything setup in the gateway, and when I test the login from the gateway I get the following in the IdP response data tab:

No IdP Response Data
The IdP response data is unavailable. Check the logs for details.

If I take a look in the logs I have the following error from the WebAuthSessionImpl Logger.

Message: Unable to handle login response

com.inductiveautomation.ignition.gateway.auth.idp.IdpAdapterException: Unable to parse the WebAuthResponse from the HTTP request

at com.inductiveautomation.ignition.gateway.auth.idp.IdpAdapter.parseAttributes(IdpAdapter.java:122)

at com.inductiveautomation.ignition.gateway.auth.idp.WebAuthSessionImpl.onLoginResponseInternal(WebAuthSessionImpl.java:199)

at com.inductiveautomation.ignition.gateway.auth.idp.WebAuthSessionImpl.lambda$onLoginResponse$2(WebAuthSessionImpl.java:220)

at com.inductiveautomation.ignition.gateway.auth.idp.WebAuthSessionImpl.mdc(WebAuthSessionImpl.java:108)

at com.inductiveautomation.ignition.gateway.auth.idp.WebAuthSessionImpl.onLoginResponse(WebAuthSessionImpl.java:220)

at com.inductiveautomation.ignition.gateway.auth.idp.IdpAdapterConfigRoutes$TestLoginWebAuthResponseHandler.handle(IdpAdapterConfigRoutes.java:301)

at com.inductiveautomation.ignition.gateway.auth.federation.FederationRoutes.callback(FederationRoutes.java:273)

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.RouteGroupCollectionServlet.serviceInternal(RouteGroupCollectionServlet.java:59)

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.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.inductiveautomation.ignition.gateway.auth.web.strategy.WebAuthStrategyException: Unable to create the XML Attribute Source from the SAML Response

at com.inductiveautomation.ignition.gateway.auth.web.strategy.saml.SAMLWebAuthStrategy.parseWebAuthResponse(SAMLWebAuthStrategy.java:59)

at com.inductiveautomation.ignition.gateway.auth.idp.IdpAdapter.parseAttributes(IdpAdapter.java:112)

... 52 common frames omitted

Caused by: com.inductiveautomation.ignition.gateway.auth.saml.binding.http.response.SAMLHttpResponseFactoryException: Unable to deserialize the SAML Response XML Document

at com.inductiveautomation.ignition.gateway.auth.saml.binding.http.response.AbstractSAMLHttpResponseFactory.create(AbstractSAMLHttpResponseFactory.java:414)

at com.inductiveautomation.ignition.gateway.auth.web.strategy.saml.SAMLWebAuthStrategy.parseWebAuthResponse(SAMLWebAuthStrategy.java:57)

... 53 common frames omitted

Caused by: com.inductiveautomation.ignition.gateway.auth.saml.serialization.SAMLDeserializerException: Unable to parse the Document

at com.inductiveautomation.ignition.gateway.auth.saml.serialization.AbstractSAMLDeserializer.deserialize(AbstractSAMLDeserializer.java:43)

at com.inductiveautomation.ignition.gateway.auth.saml.binding.http.response.AbstractSAMLHttpResponseFactory.create(AbstractSAMLHttpResponseFactory.java:412)

... 54 common frames omitted

Caused by: com.inductiveautomation.ignition.gateway.auth.saml.parsing.SAMLDocumentParserException: Expected one Signature candidate for signed node 0 and xPath /samlp:Response but got 0

at com.inductiveautomation.ignition.gateway.auth.saml.parsing.SignatureValidatingSAMLDocumentParserDecorator.getOnlyChild(SignatureValidatingSAMLDocumentParserDecorator.java:111)

at com.inductiveautomation.ignition.gateway.auth.saml.parsing.SignatureValidatingSAMLDocumentParserDecorator.validate(SignatureValidatingSAMLDocumentParserDecorator.java:124)

at com.inductiveautomation.ignition.gateway.auth.saml.parsing.SignatureValidatingSAMLDocumentParserDecorator.parse(SignatureValidatingSAMLDocumentParserDecorator.java:197)

at com.inductiveautomation.ignition.gateway.auth.saml.serialization.AbstractSAMLDeserializer.deserialize(AbstractSAMLDeserializer.java:41)

... 55 common frames omitted

Any ideas where to start? I don’t have admin access to anything with this customers Azure, so if I need to have them change anything I’ll need to be explicit. Or is there something on the Ignition side I need to do?

The root cause for why Ignition is unable to handle the IdP’s SAML Response is detailed above. Ignition does not trust the response, because the response is not signed, and you have the Validate Response Signatures setting enabled on the Ignition IdP’s configuration settings.

Is your IdP signing assertions and not signing the whole response? If so, you could disable the Validate Response Signatures setting and enable the Validate Assertion Signatures setting.

I ended up disabling the Validate Response Signatures and everything is working as expected now.

Thanks!

I would strongly recommend enabling either Validate Response Signatures or Validate Assertion Signatures (or both), otherwise a malicious user could forge a SAML Response to masquerade as any user they like, compromising the security of any session authenticated using this IdP.

What do I need to have them do on the azure side to make it work?

Well, first thing I would check is whether or not Azure intends to sign Responses and/or Assertions. Next, make sure that you have the appropriate checkboxes enabled on the Ignition side based on the answer to the previous question. Finally, make sure Ignition has the appropriate signature verifying certs / keys to validate such signatures (which is usually imported with the IdP’s metadata XML that they should provide you).

They did provide a metadata link and that’s how we got the beginning part done.

I’ll get with them tomorrow and check the other items.