hlavki / g-suite-identity-sync

G Suite to LDAP identity synchronizer
Apache License 2.0
127 stars 29 forks source link

LDAPSDKUsageException when creating an account. #56

Closed jschnare closed 4 years ago

jschnare commented 4 years ago

LDAPSDKUsageException(message='A null object was provided where a non-null object is required (non-null index 1).

One of our users is getting this exception when he tries to creates his account. We're running the latest docker image, tag 4.6.

I'm guessing that it's failing because account.getFamilyName() returns null, but I've confirmed that his gsuite account has family, given, and full name details set. Other users aren't seeing the same error.

Any idea what else I can check?

Stack trace:

LDAPSDKUsageException(message='A null object was provided where a non-null object is required (non-null index 1).  Thread stack trace:  getStackTrace(null:unknown) / ensureNotNull(Validator.java:122) / addAttribute(Entry.java:1286) / createAccount(LdapAccountServiceImpl.java:138) / createAccount(null:unknown) / createAccount(UserAccountService.java:94) / invoke0(null:native) / invoke(null:unknown) / invoke(null:unknown) / invoke(null:unknown) / performInvocation(AbstractInvoker.java:179) / invoke(AbstractInvoker.java:96) / invoke(JAXRSInvoker.java:201) / invoke(JAXRSInvoker.java:104) / run(ServiceInvokerInterceptor.java:59) / handleMessage(ServiceInvokerInterceptor.java:96) / doIntercept(PhaseInterceptorChain.java:308) / onMessage(ChainInitiationObserver.java:121) / invoke(AbstractHTTPDestination.java:267) / invokeDestination(ServletController.java:234) / invoke(ServletController.java:208) / invoke(ServletController.java:160) / invoke(CXFNonSpringServlet.java:216) / handleRequest(AbstractHTTPServlet.java:301) / doPost(AbstractHTTPServlet.java:220) / service(HttpServlet.java:707) / service(AbstractHTTPServlet.java:276) / handle(ServletHolder.java:873) / doFilter(ServletHandler.java:1623) / doFilter(WebSocketUpgradeFilter.java:214) / doFilter(ServletHandler.java:1610) / doHandle(ServletHandler.java:540) / doHandle(HttpServiceServletHandler.java:71) / handle(ScopedHandler.java:146) / handle(SecurityHandler.java:548) / handle(HandlerWrapper.java:132) / nextHandle(ScopedHandler.java:257) / doHandle(SessionHandler.java:1700) / nextHandle(ScopedHandler.java:255) / doHandle(ContextHandler.java:1345) / doHandle(HttpServiceContext.java:293) / nextScope(ScopedHandler.java:203) / doScope(ServletHandler.java:480) / doScope(SessionHandler.java:1667) / nextScope(ScopedHandler.java:201) / doScope(ContextHandler.java:1247) / handle(ScopedHandler.java:144) / handle(JettyServerHandlerCollection.java:80) / handle(HandlerWrapper.java:132) / handle(Server.java:505) / handle(HttpChannel.java:370) / onFillable(HttpConnection.java:267) / succeeded(AbstractConnection.java:305) / fillable(FillInterest.java:103) / run(ChannelEndPoint.java:117) / runTask(EatWhatYouKill.java:333) / doProduce(EatWhatYouKill.java:310) / tryProduce(EatWhatYouKill.java:168) / run(EatWhatYouKill.java:126) / run(ReservedThreadExecutor.java:366) / runJob(QueuedThreadPool.java:698) / run(QueuedThreadPool.java:804) / run(null:unknown)')
    at com.unboundid.util.Validator.ensureNotNull(Validator.java:122)
    at com.unboundid.ldap.sdk.Entry.addAttribute(Entry.java:1286)
    at eu.hlavki.identity.services.ldap.impl.LdapAccountServiceImpl.createAccount(LdapAccountServiceImpl.java:138)
    at Proxy35e92fc2_5b8b_4443_b99b_ea78a14cd1fd.createAccount(Unknown Source)
    at eu.hlavki.identity.services.rest.service.UserAccountService.createAccount(UserAccountService.java:94)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:179)
    at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96)
    at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:201)
    at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:104)
    at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59)
    at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:96)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
    at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
    at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:267)
    at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:234)
    at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:208)
    at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:160)
    at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:216)
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:301)
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:220)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:276)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:873)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1623)
    at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:214)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:540)
    at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:71)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1700)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1345)
    at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:293)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:480)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1667)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1247)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at org.eclipse.jetty.server.Server.handle(Server.java:505)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:370)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:267)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    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:333)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126)
    at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:698)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:804)
    at java.base/java.lang.Thread.run(Unknown Source)
hlavki commented 4 years ago

@jschnare, will be great if you enable log of request/response from google and look in log what response contains. As you said it looks like family name is null. thanks To enable req/resp log run:

docker-compose exec identity /opt/karaf/bin/client 'log:set INFO org.apache.cxf'

After that you can revert this operation by:

docker-compose exec identity /opt/karaf/bin/client 'log:set WARN org.apache.cxf'
jschnare commented 4 years ago

Thanks for that tip, it gave me enough info to figure it out.

I thought that the app was pulling the user details from the AdminDirectory API, where we have set the user's full name. I see now that it's reading the OpenIDConnect userinfo. In this case the user had gone to https://myaccount.google.com/personal-info/ and set his name to his first name only, no family name. The error went away once he'd set his full name.

The real issue then is that family_name is not guaranteed to be set in the OpenIDConnect response.

hlavki commented 4 years ago

thanks for info @jschnare, it's good point, that will be better to to read user info using AdminDirectory API. I will close this issue and open new one for this change.