jenkinsci / oic-auth-plugin

A Jenkins plugin which lets you login to Jenkins using your own, self-hosted or public openid connect server.
https://plugins.jenkins.io/oic-auth
MIT License
71 stars 94 forks source link

login failed with fusionauth : missing_client_id #247

Closed gulecroc closed 10 months ago

gulecroc commented 1 year ago

Jenkins and plugins versions report

Environment ```text Jenkins: 2.401.2 OS: Linux - 5.4.0-153-generic Java: 11.0.19 - Eclipse Adoptium (OpenJDK 64-Bit Server VM) --- antisamy-markup-formatter:159.v25b_c67cd35fb_ apache-httpcomponents-client-4-api:4.5.14-150.v7a_b_9d17134a_5 authentication-tokens:1.53.v1c90fd9191a_b_ bootstrap5-api:5.3.0-1 bouncycastle-api:2.29 branch-api:2.1122.v09cb_8ea_8a_724 caffeine-api:3.1.6-115.vb_8b_b_328e59d8 checks-api:2.0.0 cloudbees-bitbucket-branch-source:825.va_6a_dc46a_f97d cloudbees-folder:6.815.v0dd5a_cb_40e0e command-launcher:100.v2f6722292ee8 commons-lang3-api:3.12.0-36.vd97de6465d5b_ commons-text-api:1.10.0-36.vc008c8fcda_7b_ configuration-as-code:1647.ve39ca_b_829b_42 credentials:1254.vb_96f366e7b_a_d credentials-binding:604.vb_64480b_c56ca_ data-tables-api:1.13.5-1 display-url-api:2.3.7 docker-commons:439.va_3cb_0a_6a_fb_29 durable-task:510.v324450f8dca_4 echarts-api:5.4.0-5 favorite:2.4.2 font-awesome-api:6.4.0-2 git:5.2.0 git-client:4.4.0 git-server:99.va_0826a_b_cdfa_d github:1.37.1 github-api:1.314-431.v78d72a_3fe4c3 github-branch-source:1728.v859147241f49 handy-uri-templates-2-api:2.1.8-22.v77d5b_75e6953 htmlpublisher:1.31 instance-identity:173.va_37c494ec4e5 ionicons-api:56.v1b_1c8c49374e jackson2-api:2.15.2-350.v0c2f3f8fc595 jakarta-activation-api:2.0.1-3 jakarta-mail-api:2.0.1-3 javax-activation-api:1.2.0-6 javax-mail-api:1.6.2-9 jaxb:2.3.8-1 jdk-tool:66.vd8fa_64ee91b_d jjwt-api:0.11.5-77.v646c772fddb_0 jquery3-api:3.7.0-1 jsch:0.2.8-65.v052c39de79b_2 junit:1217.v4297208a_a_b_ce kubernetes:3971.v94b_4c914ca_75 kubernetes-client-api:6.4.1-215.v2ed17097a_8e9 kubernetes-credentials:0.10.0 locale:314.v22ce953dfe9e lockable-resources:1172.v4b_8fc8eed570 mailer:457.v3f72cb_e015e5 mapdb-api:1.0.9-28.vf251ce40855d matrix-auth:3.1.10 matrix-project:789.v57a_725b_63c79 metrics:4.2.18-439.v86a_20b_a_8318b_ mina-sshd-api-common:2.10.0-69.v28e3e36d18eb_ mina-sshd-api-core:2.10.0-69.v28e3e36d18eb_ oic-auth:2.6 okhttp-api:4.11.0-145.vcb_8de402ef81 pipeline-build-step:496.v2449a_9a_221f2 pipeline-graph-analysis:202.va_d268e64deb_3 pipeline-groovy-lib:656.va_a_ceeb_6ffb_f7 pipeline-input-step:468.va_5db_051498a_4 pipeline-milestone-step:111.v449306f708b_7 pipeline-model-api:2.2144.v077a_d1928a_40 pipeline-model-definition:2.2144.v077a_d1928a_40 pipeline-model-extensions:2.2144.v077a_d1928a_40 pipeline-rest-api:2.33 pipeline-stage-step:305.ve96d0205c1c6 pipeline-stage-tags-metadata:2.2144.v077a_d1928a_40 pipeline-stage-view:2.33 plain-credentials:143.v1b_df8b_d3b_e48 plugin-util-api:3.3.0 pubsub-light:1.17 role-strategy:667.vd7f94d9fddf9 scm-api:676.v886669a_199a_a_ script-security:1251.vfe552ed55f8d snakeyaml-api:1.33-95.va_b_a_e3e47b_fa_4 sse-gateway:1.26 ssh-credentials:305.v8f4381501156 sshd:3.303.vefc7119b_ec23 structs:324.va_f5d6774f3a_d subversion:2.17.2 token-macro:359.vb_cde11682e0c trilead-api:2.84.v72119de229b_7 variant:59.vf075fe829ccb workflow-aggregator:596.v8c21c963d92d workflow-api:1232.v1679fa_2f0f76 workflow-basic-steps:1017.vb_45b_302f0cea_ workflow-cps:3717.va_180a_fe9d3cd workflow-durable-task-step:1247.v7f9dfea_b_4fd0 workflow-job:1316.vd2290d3341a_f workflow-multibranch:756.v891d88f2cd46 workflow-scm-step:415.v434365564324 workflow-step-api:639.v6eca_cd8c04a_a_ workflow-support:839.v35e2736cfd5c ```

What Operating System are you using (both controller, and any agents involved in the problem)?

Jenkins installation with helm chart

Reproduction steps

Configuration was set from Jenkins UI with clientId, clientSecret and auto configuration URL. The exported configuration as code is :

  securityRealm:
    oic:
      authorizationServerUrl: "https://fusionauth.domain.com/oauth2/authorize"
      automanualconfigure: "auto"
      clientId: "8a682f49-b0c6-4a30-87a2-a817aff5e6d5"
      clientSecret: "#secret#"
      disableSslVerification: false
      endSessionEndpoint: "https://fusionauth.domain.com/oauth2/logout"
      escapeHatchSecret: "#secret#"
      logoutFromOpenidProvider: false
      scopes: "openid offline_access"
      tokenAuthMethod: "client_secret_post"
      tokenServerUrl: "https://fusionauth.domain.com/oauth2/token"
      userInfoServerUrl: "https://fusionauth.domain.com/oauth2/userinfo"
      wellKnownOpenIDConfigurationUrl: "https://fusionauth.domain.com/.well-known/openid-configuration/0dd8611f-9c21-b5a4-1f64-d43fb0c2caf2"

Click on login button from jenkins. Fusionauth prompt login form, and URL contains client_id :

https://fusionauth.domain.com/oauth2/authorize?client_id=8a682f49-b0c6-4a30-87a2-a817aff5e6d5&redirect_uri=https://jenkins.domain.com/securityRealm/finishLogin&response_type=code&scope=openid%20offline_access&state=NmY2ZjJjMjctMWVhNS00&nonce=c233f93e-03c4-4456-a3d2-304934539fb9

After authenticated with fusionauth, back to jenkins. User state is authenticated in URL :

https://jenkins.domain.com/securityRealm/finishLogin?code=kzoihiYD9P0oEivgOWQlPrgVyT6GAKL000bdddux53g&locale=en&state=OTQ4ZDFlMzUtNTk0Ny00&userState=Authenticated

But an error appears in jenkins with missing_client_id :

2023-07-19 12:49:13.381+0000 [id=17]    WARNING h.i.i.InstallUncaughtExceptionHandler#handleException: Caught unhandled exception with ID b061ded5-5134-4c9e-adb0-25de2c529533
com.google.api.client.auth.oauth2.TokenResponseException: 400
POST https://retd-k8s-auth-test.koeos.com/oauth2/token
{
  "error" : "invalid_request",
  "error_description" : "The request is missing a required parameter: client_id",
  "error_reason" : "missing_client_id"
}
    at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:103)
    at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:308)
    at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:324)
    at org.jenkinsci.plugins.oic.OicSecurityRealm$3.onSuccess(OicSecurityRealm.java:759)
    at org.jenkinsci.plugins.oic.OicSession.doFinishLogin(OicSession.java:145)
    at org.jenkinsci.plugins.oic.OicSecurityRealm.doFinishLogin(OicSecurityRealm.java:1069)
    at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:710)
    at org.kohsuke.stapler.Function$MethodFunction.invoke(Function.java:397)
    at org.kohsuke.stapler.Function$InstanceFunction.invoke(Function.java:409)
    at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:207)
    at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:140)
    at org.kohsuke.stapler.MetaClass$11.doDispatch(MetaClass.java:558)
    at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:59)
    at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:770)
    at org.kohsuke.stapler.Stapler.invoke(Stapler.java:900)
    at org.kohsuke.stapler.MetaClass$2.doDispatch(MetaClass.java:224)
    at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:59)
    at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:770)
    at org.kohsuke.stapler.Stapler.invoke(Stapler.java:900)
    at org.kohsuke.stapler.Stapler.invoke(Stapler.java:698)
    at org.kohsuke.stapler.Stapler.service(Stapler.java:248)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:764)
    at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1665)
    at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:157)
    at org.jenkinsci.plugins.ssegateway.Endpoint$SSEListenChannelFilter.doFilter(Endpoint.java:248)
    at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:154)
    at hudson.plugins.locale.LocaleFilter.doFilter(LocaleFilter.java:42)
    at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:154)
    at jenkins.security.ResourceDomainFilter.doFilter(ResourceDomainFilter.java:81)
    at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:154)
    at jenkins.telemetry.impl.UserLanguages$AcceptLanguageFilter.doFilter(UserLanguages.java:129)
    at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:154)
    at jenkins.metrics.impl.MetricsFilter.doFilter(MetricsFilter.java:125)
    at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:154)
    at hudson.util.PluginServletFilter.doFilter(PluginServletFilter.java:160)
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
    at hudson.security.csrf.CrumbFilter.doFilter(CrumbFilter.java:160)
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:94)
    at jenkins.security.AcegiSecurityExceptionFilter.doFilter(AcegiSecurityExceptionFilter.java:52)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:99)
    at hudson.security.UnwrapSecurityExceptionFilter.doFilter(UnwrapSecurityExceptionFilter.java:54)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:99)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:99)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:99)
    at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:145)
    at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:101)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:99)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:227)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:221)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:99)
    at jenkins.security.BasicHeaderProcessor.doFilter(BasicHeaderProcessor.java:97)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:99)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:117)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at hudson.security.HttpSessionContextIntegrationFilter2.doFilter(HttpSessionContextIntegrationFilter2.java:63)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:99)
    at hudson.security.ChainedServletFilter.doFilter(ChainedServletFilter.java:111)
    at hudson.security.HudsonFilter.doFilter(HudsonFilter.java:172)
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
    at org.kohsuke.stapler.compression.CompressionFilter.doFilter(CompressionFilter.java:53)
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
    at hudson.util.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:86)
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
    at org.kohsuke.stapler.DiagnosticThreadNameFilter.doFilter(DiagnosticThreadNameFilter.java:30)
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
    at jenkins.security.SuspiciousRequestFilter.doFilter(SuspiciousRequestFilter.java:38)
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:527)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:131)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:549)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:223)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1570)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1383)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:484)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1543)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1305)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
    at org.eclipse.jetty.server.Server.handle(Server.java:563)
    at org.eclipse.jetty.server.HttpChannel.lambda$handle$0(HttpChannel.java:505)
    at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:762)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:497)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:282)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:314)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100)
    at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:416)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:385)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:272)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.lambda$new$0(AdaptiveExecutionStrategy.java:140)
    at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:411)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:934)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1078)
    at java.base/java.lang.Thread.run(Thread.java:829)

Expected Results

User is authenticated

Actual Results

Error with missing client_id

Anything else?

Configuration was working good. After upgrade jenkins oic-auth-plugin from 2.5 to 2.6, and fusionauth from 1.42.0 to 1.46.0, I got this error. I rollback jenkins plugin and fusionauth, but the error is still there. I try to enable more log from jenkins without success :

jenkins:
 log:
    recorders:
    - loggers:
      - level: "FINEST"
        name: "com.google.api.client.auth.oauth2"
      - level: "FINEST"
        name: "org.jenkinsci.plugins.oic"
      name: "oauth

I try to change tokenAuthMethod: "client_secret_post" and "client_secret_basic" I try to enable/disable Nonce.

Below the openid well-known configuration :

{
  "authorization_endpoint" : "https://fusionauth.domain.com/oauth2/authorize",
  "backchannel_logout_supported" : false,
  "claims_supported" : [
    "applicationId",
    "at_hash",
    "aud",
    "authenticationType",
    "birthdate",
    "c_hash",
    "email",
    "email_verified",
    "exp",
    "family_name",
    "given_name",
    "iat",
    "iss",
    "jti",
    "middle_name",
    "name",
    "nbf",
    "nonce",
    "phone_number",
    "picture",
    "preferred_username",
    "roles",
    "sub"
  ],
  "device_authorization_endpoint" : "https://fusionauth.domain.com/oauth2/device_authorize",
  "end_session_endpoint" : "https://fusionauth.domain.com/oauth2/logout",
  "frontchannel_logout_supported" : true,
  "grant_types_supported" : [
    "authorization_code",
    "password",
    "implicit",
    "refresh_token",
    "urn:ietf:params:oauth:grant-type:device_code"
  ],
  "id_token_signing_alg_values_supported" : [
    "ES256",
    "ES384",
    "ES512",
    "HS256",
    "HS384",
    "HS512",
    "RS256",
    "RS384",
    "RS512"
  ],
  "issuer" : "acme.com",
  "jwks_uri" : "https://fusionauth.domain.com/.well-known/jwks.json",
  "response_modes_supported" : [
    "form_post",
    "fragment",
    "query"
  ],
  "response_types_supported" : [
    "code",
    "id_token",
    "token id_token"
  ],
  "scopes_supported" : [
    "openid",
    "offline_access"
  ],
  "subject_types_supported" : [
    "public"
  ],
  "token_endpoint" : "https://fusionauth.domain.com/oauth2/token",
  "token_endpoint_auth_methods_supported" : [
    "client_secret_basic",
    "client_secret_post",
    "none"
  ],
  "userinfo_endpoint" : "https://fusionauth.domain.com/oauth2/userinfo",
  "userinfo_signing_alg_values_supported" : [
    "ES256",
    "ES384",
    "ES512",
    "RS256",
    "RS384",
    "RS512",
    "HS256",
    "HS384",
    "HS512"
  ]
}

Seems like https://github.com/jenkinsci/oic-auth-plugin/issues/179

ethantmcgee commented 1 year ago

I was able to get this working today with manual configuration instead of auto.

image

I had to set a few settings under advanced

image
michael-doubez commented 1 year ago

Hello, Thank you, that's interesting - could you share the difference between the url in the discovery endpoint and the one manually configured ?

gulecroc commented 1 year ago

I confirm it work well for me with the following configuration :

If I switch to authentication method = post I got the error missing_client_id.

With auto configuration, authentication method is set to client_secret_post so I think it's the problem with fusionauth.