#1797  Group assignment issues with EntraID
Closed
Tobias opened 1 month ago

Hi Robin,

we are using EntraID as a link between two domains. We synchronize certain groups from each domain to EntraID. Reference onedev/server#1719 The group names used for the local AD login are the same as for EntraID since they are synchronized to EntraID.

The login via EntraID works, the group assignment only works if a specific dynamic EntraID group has been created in OneDev.

Are there any issues with local synchronized groups? How exactly do you query the groups in EntraID?

Is it possible to get more information about the request and authentication with external authentication in the server log, perhaps with a label in the Docker container?

Robin Shen commented 1 month ago

OneDev get group ids via groups claim, then calls ms graph api to get associated group names. And OneDev account will be assigned to same OneDev group if it exists.

The code to call ms graph api to get group names:

https://code.onedev.io/onedev/server/~files/afbe48836d390633cc1fd87fa38e8ff4ca19a563/server-plugin/server-plugin-sso-openid/src/main/java/io/onedev/server/plugin/sso/openid/EntraIdConnector.java?position=source-111.1-151.3-1

Tobias commented 1 month ago

The code helped to solve the problem, thank you very much. We have now used the single sign-on provider OpenID. Now all groups of the user who wants to log in to OneDev using EntraID are queried.

We have entered the following data:

  • Configuration Discovery URL: https://login.microsoftonline.com/(Tenant ID)/v2.0/.well-known/openid-configuration
  • Client ID: Application Client ID
  • Client Secret: Value (Client Secret)
  • Request Scopes: openid email profile
  • Group Claim: groups

The following settings are set for the groups claim:

  • ID: sAMAccountName
  • Access: Group ID
  • SAML: Group ID
Robin Shen commented 1 month ago

So at your side, the id token will return group name directly instead of group uuid, and you don't need to call graph api to convert to group name?

Tobias commented 1 month ago

In the setup with EntraID as the single sign-on provider, we would have had to convert the group ID to the group names. Here the ID in the group claim settings was set to "Group ID" and not all of the user's groups were returned.

With the sAMAccountName ID setting, the group name is returned, eliminating the need for conversion.

Tobias commented 1 month ago

Since switching to the sign-on provider OpenID, an error has been appearing in our server log. I could not find a connection with a login to the OneDev server.

2024-03-19 07:06:26,374 WARN  [qtp1720013107-812] o.a.w.core.util.lang.WicketObjects Could not resolve class [io.onedev.server.plugin.sso.openid.openidconnector]
java.lang.ClassNotFoundException: io.onedev.server.plugin.sso.openid.openidconnector
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:476)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:594)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:527)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:398)
	at org.apache.wicket.application.AbstractClassResolver.resolveClass(AbstractClassResolver.java:111)
	at org.apache.wicket.core.util.lang.WicketObjects.resolveClass(WicketObjects.java:71)
	at org.apache.wicket.core.request.mapper.BasicResourceReferenceMapper.resolveClass(BasicResourceReferenceMapper.java:157)
	at org.apache.wicket.core.request.mapper.BasicResourceReferenceMapper.mapRequest(BasicResourceReferenceMapper.java:133)
	at org.apache.wicket.request.mapper.ParentPathReferenceRewriter.mapRequest(ParentPathReferenceRewriter.java:84)
	at org.apache.wicket.request.mapper.CompoundRequestMapper.mapRequest(CompoundRequestMapper.java:147)
	at org.apache.wicket.request.cycle.RequestCycle.resolveRequestHandler(RequestCycle.java:184)
	at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:214)
	at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:288)
	at org.apache.wicket.protocol.ws.AbstractUpgradeFilter.processRequestCycle(AbstractUpgradeFilter.java:70)
	at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:203)
	at org.apache.wicket.protocol.http.WicketServlet.doGet(WicketServlet.java:137)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at io.onedev.server.web.DefaultWicketServlet.lambda$service$0(DefaultWicketServlet.java:45)
	at io.onedev.server.persistence.DefaultSessionManager.lambda$run$0(DefaultSessionManager.java:108)
	at io.onedev.server.persistence.DefaultSessionManager.call(DefaultSessionManager.java:90)
	at io.onedev.server.persistence.DefaultSessionManager.run(DefaultSessionManager.java:107)
	at io.onedev.server.web.DefaultWicketServlet.service(DefaultWicketServlet.java:42)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:799)
	at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1656)
	at com.google.inject.servlet.DefaultFilterPipeline.dispatch(DefaultFilterPipeline.java:47)
	at com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:133)
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
	at io.onedev.server.git.GoGetFilter.doFilter(GoGetFilter.java:87)
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
	at io.onedev.server.git.GitLfsFilter.doFilter(GitLfsFilter.java:462)
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
	at io.onedev.server.git.GitFilter.doFilter(GitFilter.java:369)
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:458)
	at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:373)
	at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
	at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
	at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:370)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
	at io.onedev.server.security.CorsFilter.doFilter(CorsFilter.java:47)
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
	at io.onedev.server.jetty.DisableTraceFilter.doFilter(DisableTraceFilter.java:28)
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:552)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:505)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
	at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:772)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
	at org.eclipse.jetty.server.Server.handle(Server.java:516)
	at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487)
	at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:732)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:479)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277)
	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:338)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:409)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034)
	at java.base/java.lang.Thread.run(Thread.java:829)
Robin Shen commented 1 month ago

Is this affecting your login? Are you able to reproduce this?

Tobias commented 1 month ago

I am still clarifying whether the error only occurs when a specific user logs in. The logins are not affected by the error for any user.

We are currently running AD login (External Authenticator/AD) and EntraID login (SSO/OpenID) in parallel.

Robin Shen changed state to 'Closed' 1 month ago
Previous Value Current Value
Open
Closed
Robin Shen commented 1 month ago

Unable to reproduce. Reopen if there is more info.

issue 1 of 1
Type
Question
Priority
Normal
Assignee
Labels
No labels
Issue Votes (0)
Watchers (3)
Reference
onedev/server#1797
Please wait...
Page is in error, reload to recover