Issue with OAuth2login user creation

**Application Name: Reference Application **Version Number: 2.11

Question: I built the openmrs-module-oauth2login and followed all the instructions from here using Google OAuth2. So I created a new user and assigned an email to it(Google account). But when I login from that Google account it shows me error that the user already exists. I think the Google OAuth2 API is trying to create a new user every time and it’s and issue with the mapping. Can someone please help me out?

This is the error I am getting:

HTTP ERROR 500 javax.servlet.ServletException: org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.RuntimeException: The user '103632344071261943787' could not be authenticated with the identity provider.
URI:	/openmrs/oauth2login
STATUS:	500
MESSAGE:	javax.servlet.ServletException: org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.RuntimeException: The user '103632344071261943787' could not be authenticated with the identity provider.
SERVLET:	oauth2login
CAUSED BY:	javax.servlet.ServletException: org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.RuntimeException: The user '103632344071261943787' could not be authenticated with the identity provider.
CAUSED BY:	org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.RuntimeException: The user '103632344071261943787' could not be authenticated with the identity provider.
CAUSED BY:	java.lang.RuntimeException: The user '103632344071261943787' could not be authenticated with the identity provider.
CAUSED BY:	org.openmrs.api.context.ContextAuthenticationException: The user Arun Ajmera (103632344071261943787) already exists, it could therefore not be created.
CAUSED BY:	org.openmrs.api.APIException: The user Arun Ajmera (103632344071261943787) already exists, it could therefore not be created.
Caused by:
javax.servlet.ServletException: org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.RuntimeException: The user '103632344071261943787' could not be authenticated with the identity provider.
	at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:162)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
	at org.eclipse.jetty.server.Server.handle(Server.java:501)
	at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:383)
	at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:556)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:273)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
	at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
	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:375)
	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.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.RuntimeException: The user '103632344071261943787' could not be authenticated with the identity provider.
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at org.eclipse.jetty.servlet.ServletHolder$NotAsyncServlet.service(ServletHolder.java:1411)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:763)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1651)
	at org.openmrs.module.web.filter.ForcePasswordChangeFilter.doFilter(ForcePasswordChangeFilter.java:60)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1638)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter.doFilter(OAuth2ClientContextFilter.java:60)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1638)
	at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:226)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1638)
	at org.openmrs.module.web.filter.ModuleFilterChain.doFilter(ModuleFilterChain.java:73)
	at org.openmrs.module.owa.filter.OwaFilter.doFilter(OwaFilter.java:93)
	at org.openmrs.module.owa.filter.OwaFilter.doFilter(OwaFilter.java:71)
	at org.openmrs.module.web.filter.ModuleFilterChain.doFilter(ModuleFilterChain.java:71)
	at org.openmrs.module.oauth2login.web.filter.OAuth2LoginRequestFilter.doFilter(OAuth2LoginRequestFilter.java:71)
	at org.openmrs.module.web.filter.ModuleFilterChain.doFilter(ModuleFilterChain.java:71)
	at org.openmrs.module.web.filter.ModuleFilter.doFilter(ModuleFilter.java:57)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1638)
	at org.openmrs.web.filter.OpenmrsFilter.doFilterInternal(OpenmrsFilter.java:105)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1638)
	at org.springframework.orm.hibernate5.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:156)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1638)
	at org.openmrs.web.filter.StartupFilter.doFilter(StartupFilter.java:108)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1638)
	at org.openmrs.web.filter.StartupFilter.doFilter(StartupFilter.java:108)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1638)
	at org.openmrs.web.filter.StartupFilter.doFilter(StartupFilter.java:108)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1638)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1630)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:567)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:602)
	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:1610)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1377)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:507)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1580)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1292)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
	at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:191)
	at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:146)
	... 17 more
Caused by: java.lang.RuntimeException: The user '103632344071261943787' could not be authenticated with the identity provider.
	at org.openmrs.module.oauth2login.web.controller.OAuth2LoginController.login(OAuth2LoginController.java:80)
	at sun.reflect.GeneratedMethodAccessor757.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	... 97 more
Caused by: org.openmrs.api.context.ContextAuthenticationException: The user Arun Ajmera (103632344071261943787) already exists, it could therefore not be created.
	at org.openmrs.module.oauth2login.authscheme.UsernameAuthenticationScheme.createUser(UsernameAuthenticationScheme.java:93)
	at org.openmrs.module.oauth2login.authscheme.UsernameAuthenticationScheme.authenticate(UsernameAuthenticationScheme.java:77)
	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 org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
	at com.sun.proxy.$Proxy401.authenticate(Unknown Source)
	at org.openmrs.api.context.UserContext.authenticate(UserContext.java:114)
	at org.openmrs.api.context.Context.authenticate(Context.java:345)
	at org.openmrs.module.oauth2login.web.controller.OAuth2LoginController.login(OAuth2LoginController.java:77)
	... 109 more
Caused by: org.openmrs.api.APIException: The user Arun Ajmera (103632344071261943787) already exists, it could therefore not be created.
	at org.openmrs.api.context.Daemon$2.run(Daemon.java:143)

Hi @hardikaj, in the very last lines of it:

org.openmrs.api.APIException:
  The user Arun Ajmera (103632344071261943787) already exists, it could therefore not be created.

That should actually not happen because if the user already exists, it should not be null here, and the creation should not be triggered. But perhaps have you encountered a new bug…

So somehow the scheme doesn’t find the user and hence attempts to create it, but then lower down this happens.

And as you can see the latest condition checks a lot of stuff:

  1. user.getId() != null
  2. Context.getUserService().getUser(user.getId()) != null)
  3. Context.getUserService().getUserByUuid(user.getUuid()) != null
  4. Context.getUserService().getUserByUsername(user.getUsername()) != null
  5. (user.getEmail() != null && Context.getUserService().getUserByUsernameOrEmail(user.getEmail()) != null)

Could you check in your OpenMRS database if any of those conditions are true for this user Arun Ajmera (103632344071261943787)?

1 Like

Hey @mksd, thanks for the reply! I found out that the oauth2login module maps the google account user id(21 letter unique numeric string) to the OpenMRS username. SO when login in from the Google OAuth, it tries to find the username with the unique google user ID but it doesn’t so it creates new one but it cant since there is already a user present with the same email. Let me know if you find something on this!

But how is there already a user with that email? Was this user created before OAuth 2 Login was installed?

Yes , I assigned the email to the new user explicitly so that when he login, he/ she can see the applications on their screen instead of blank.

Actually I am trying to implement this for a hospital and I need to assign 100 workers, their user accounts with OAuth. Can you tell me the fastest way to do that?

Also, after login in from OAuth, the OpenMRS login page opens. So basically its asking for login credentials twice(once on Google OAuth and once on OpenMRS login page). Can you tell me how can I by-pass that?

Thanks again for such fast replies, its hard these days to find active communities for open source project!

I made the openmrs module OAuth 2login also understood all the directions from here doing Google OAuth2. So I built a unique user and drafted an email to it(Google story). However, meanwhile, I log in to that Google report, which dispenses me a mistake that the user previously survives. I remember the Google OAuth2 API is working to build a new user each time, and it’s an argument by this mapping. Prison, someone, please support me escape?

I had the same issue.

It is trying to map the unique google user ID(21 digits unique string) to username in OpenMRS(For more info check users table in the database).

So if you insert a user with the unique google user ID as OpenMRS user name and then use the google oauth2 API, it should work fine.

@hardikaj, knowing that the OpenMRS username cannot be an email address (that’s a constraint from Core), what would you suggest?

The current suggested mapping with Google API for the OpenMRS username is this:

openmrs.mapping.user.username=sub

I wish this could be possible, but it isn’t (because of Core):

openmrs.mapping.user.username=email

Even with this setting/global property? https://github.com/openmrs/openmrs-core/blob/2.0.0/api/src/main/java/org/openmrs/util/OpenmrsConstants.java#L992-L993

2 Likes

Thanks @dkayiwa (you are an encyclopedia :slight_smile: ).


Ok so @hardikaj and @samikhan, the following OAuth2 mapping could be used with Google API:

openmrs.mapping.user.username=email

If the GP "user.requireEmailAsUsername" is set to "true".

2 Likes

Wow, you @mksd and @dkayiwa really know all your stuff :joy:

Thanks again!

I have the same corresponding issue. That is trying to plan the individual google user ID(21 digits unique order) to the user style in OpenMRS(For further info verify the user’s schedule in the database). Therefore if you enter a user with a different google user ID because OpenMRS user title and then practice the google oauth2 API, it should work accurately.

yeah that is working fine but I want to give a customized username to the user instead of a 21 digit string

@hardikaj you can pretty much do whatever mapping you want between the user info JSON and the required members of the OpenMRS User and Person, but that also depends on the control that you have on the identity management platform to configure the user info JSON.

With Google API you do not have much control on how to construct the user info JSON, if at all.