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 92 forks source link

java.lang.NullPointerException: Cannot invoke "java.net.URI.toURL()" because the return value of "com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata.getJWKSetURI()" is null #436

Open sharpjl opened 4 days ago

sharpjl commented 4 days ago

Jenkins and plugins versions report

Environment ```text Jenkins: 2.462.3 OS: Linux - 6.1.109-118.189.amzn2023.x86_64 Java: 17.0.12 - Eclipse Adoptium (OpenJDK 64-Bit Server VM) --- active-directory:2.37 ant:511.v0a_a_1a_334f41b_ antisamy-markup-formatter:162.v0e6ec0fcfcf6 apache-httpcomponents-client-4-api:4.5.14-208.v438351942757 asm-api:9.7.1-97.v4cc844130d97 authentication-tokens:1.119.v50285141b_7e1 authorize-project:1.7.2 aws-credentials:231.v08a_59f17d742 aws-java-sdk:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-api-gateway:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-autoscaling:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-cloudformation:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-cloudfront:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-codebuild:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-codedeploy:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-ec2:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-ecr:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-ecs:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-efs:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-elasticbeanstalk:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-elasticloadbalancingv2:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-iam:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-kinesis:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-lambda:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-logs:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-minimal:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-organizations:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-secretsmanager:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-sns:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-sqs:1.12.772-474.v7f79a_2046a_fb_ aws-java-sdk-ssm:1.12.772-474.v7f79a_2046a_fb_ aws-parameter-store:1.2.2 aws-secrets-manager-credentials-provider:1.214.va_0a_d8268d068 blueocean:1.27.16 blueocean-bitbucket-pipeline:1.27.16 blueocean-commons:1.27.16 blueocean-config:1.27.16 blueocean-core-js:1.27.16 blueocean-dashboard:1.27.16 blueocean-display-url:2.4.3 blueocean-events:1.27.16 blueocean-git-pipeline:1.27.16 blueocean-github-pipeline:1.27.16 blueocean-i18n:1.27.16 blueocean-jwt:1.27.16 blueocean-personalization:1.27.16 blueocean-pipeline-api-impl:1.27.16 blueocean-pipeline-editor:1.27.16 blueocean-pipeline-scm-api:1.27.16 blueocean-rest:1.27.16 blueocean-rest-impl:1.27.16 blueocean-web:1.27.16 bootstrap5-api:5.3.3-1 bouncycastle-api:2.30.1.78.1-248.ve27176eb_46cb_ branch-api:2.1178.v969d9eb_c728e build-name-setter:2.4.3 caffeine-api:3.1.8-133.v17b_1ff2e0599 checks-api:2.2.1 cloudbees-bitbucket-branch-source:888.v8e6d479a_1730 cloudbees-folder:6.955.v81e2a_35c08d3 command-launcher:115.vd8b_301cc15d0 commons-compress-api:1.26.1-2 commons-lang3-api:3.17.0-84.vb_b_938040b_078 commons-text-api:1.12.0-129.v99a_50df237f7 configuration-as-code:1850.va_a_8c31d3158b_ configuration-as-code-secret-ssm:1.0.1 copyartifact:749.vfb_dca_a_9b_6549 credentials:1384.vf0a_2ed06f9c6 credentials-binding:681.vf91669a_32e45 data-tables-api:2.1.8-1 display-url-api:2.204.vf6fddd8a_8b_e9 docker-commons:443.v921729d5611d docker-workflow:580.vc0c340686b_54 durable-task:577.v2a_8a_4b_7c0247 ec2:1715.vb_9e9e841ca_94 echarts-api:5.5.1-1 eddsa-api:0.3.0-4.v84c6f0f4969e favorite:2.221.v19ca_666b_62f5 folder-properties:1.2.1 font-awesome-api:6.6.0-2 git:5.5.2 git-client:5.0.0 github:1.40.0 github-api:1.321-468.v6a_9f5f2d5a_7e github-branch-source:1797.v86fdb_4d57d43 gitlab-plugin:1.8.2 greenballs:1.15.1 gson-api:2.11.0-85.v1f4e87273c33 handy-uri-templates-2-api:2.1.8-30.v7e777411b_148 hashicorp-vault-plugin:370.v946b_53544a_30 htmlpublisher:1.36 instance-identity:201.vd2a_b_5a_468a_a_6 ionicons-api:74.v93d5eb_813d5f jackson2-api:2.17.0-379.v02de8ec9f64c jakarta-activation-api:2.1.3-1 jakarta-mail-api:2.1.3-1 javax-activation-api:1.2.0-7 javax-mail-api:1.6.2-10 jaxb:2.3.9-1 jdk-tool:80.v8a_dee33ed6f0 jenkins-design-language:1.27.16 jenkinslint:0.14.0 jersey2-api:2.44-151.v6df377fff741 jjwt-api:0.11.5-112.ve82dfb_224b_a_d job-dsl:1.89 joda-time-api:2.13.0-93.v9934da_29b_a_e9 jquery3-api:3.7.1-2 jsch:0.2.16-86.v42e010d9484b_ json-api:20240303-101.v7a_8666713110 json-path-api:2.9.0-118.v7f23ed82a_8b_8 junit:1304.vc85a_b_ca_96613 ldap:725.v3cb_b_711b_1a_ef lockable-resources:1315.v4ea_8e5159ec8 log-parser:2.3.5 mailer:488.v0c9639c1a_eb_3 mask-passwords:173.v6a_077a_291eb_5 matrix-auth:3.2.2 matrix-project:839.vff91cd7e3a_b_2 metrics:4.2.21-451.vd51df8df52ec mina-sshd-api-common:2.14.0-133.vcc091215a_358 mina-sshd-api-core:2.14.0-133.vcc091215a_358 node-iterator-api:55.v3b_77d4032326 oic-auth:4.355.v3a_fb_fca_b_96d4 okhttp-api:4.11.0-172.vda_da_1feeb_c6e pipeline-build-step:540.vb_e8849e1a_b_d8 pipeline-graph-analysis:216.vfd8b_ece330ca_ pipeline-groovy-lib:740.va_2701257fe8d pipeline-input-step:495.ve9c153f6067b_ pipeline-milestone-step:119.vdfdc43fc3b_9a_ pipeline-model-api:2.2214.vb_b_34b_2ea_9b_83 pipeline-model-definition:2.2214.vb_b_34b_2ea_9b_83 pipeline-model-extensions:2.2214.vb_b_34b_2ea_9b_83 pipeline-rest-api:2.34 pipeline-stage-step:312.v8cd10304c27a_ pipeline-stage-tags-metadata:2.2214.vb_b_34b_2ea_9b_83 pipeline-stage-view:2.34 pipeline-utility-steps:2.18.0 plain-credentials:183.va_de8f1dd5a_2b_ plugin-util-api:5.1.0 powershell:2.1 prism-api:1.29.0-17 prometheus:787.v52e8f47488fc pubsub-light:1.18 rebuild:332.va_1ee476d8f6d resource-disposer:0.24 role-strategy:743.v142ea_b_d5f1d3 s3:483.vcb_db_3dcee68f scm-api:696.v778d637b_a_762 script-security:1365.v4778ca_84b_de5 slack:751.v2e44153c8fe1 snakeyaml-api:2.3-123.v13484c65210a_ sse-gateway:1.27 ssh-agent:376.v8933585c69d3 ssh-credentials:343.v884f71d78167 sshd:3.330.vc866a_8389b_58 statusmonitor:1.3 structs:338.v848422169819 template-project:1.5.2 terraform:1.0.10 timestamper:1.27 token-macro:400.v35420b_922dcb_ trilead-api:2.147.vb_73cc728a_32e uno-choice:2.8.4 variant:60.v7290fc0eb_b_cd workflow-aggregator:600.vb_57cdd26fdd7 workflow-api:1336.vee415d95c521 workflow-basic-steps:1058.vcb_fc1e3a_21a_9 workflow-cps:3969.vdc9d3a_efcc6a_ workflow-durable-task-step:1371.vb_7cec8f3b_95e workflow-job:1436.vfa_244484591f workflow-multibranch:795.ve0cb_1f45ca_9a_ workflow-scm-step:427.v4ca_6512e7df1 workflow-step-api:678.v3ee58b_469476 workflow-support:926.v9f4f9b_b_98c19 ws-cleanup:0.47 ```

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

Single Jenkins server, Linux - 6.1.109-118.189.amzn2023.x86_64

Reproduction steps

Recently upgraded oic-auth plugin from v4.355 to v4.388. When trying to access the jenkins console, I received a 503 error and found this in the jenkins logs:

2024-10-13 02:22:13.038+0000 [id=32]    SEVERE  jenkins.InitReactorRunner$1#onTaskFailed: Failed ConfigurationAsCode.init
hudson.model.Descriptor$FormException: issuer is mandatory
        at PluginClassLoader for oic-auth//org.jenkinsci.plugins.oic.OicServerManualConfiguration.validateNonNull(OicServerManualConfiguration.java:175)
        at PluginClassLoader for oic-auth//org.jenkinsci.plugins.oic.OicServerManualConfiguration.<init>(OicServerManualConfiguration.java:53)
Caused: java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Unknown Source)
        at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
        at PluginClassLoader for configuration-as-code//io.jenkins.plugins.casc.impl.configurators.DataBoundConfigurator.tryConstructor(DataBoundConfigurator.java:181)
Caused: io.jenkins.plugins.casc.ConfiguratorException: manual: Failed to construct instance of class org.jenkinsci.plugins.oic.OicServerManualConfiguration.
 Constructor: public org.jenkinsci.plugins.oic.OicServerManualConfiguration(java.lang.String,java.lang.String,java.lang.String) throws hudson.model.Descriptor$FormException.
 Arguments: [null, java.lang.String, java.lang.String].
 Expected Parameters: issuer java.lang.String, tokenServerUrl java.lang.String, authorizationServerUrl java.lang.String

Found release notes here saying:

4.388.v4f73328eb_d2c
4 days ago
💥 Breaking changes
[!CAUTION]
The plugin now requires that the Issuer is set to enforce security and there is no option to disable this requirement as it is mandated in the Open ID Connect specification.
As such users who do not use automatic configuration via the well-known endpoint must first update to 4.355.v3a_fb_fca_b_96d4 and configure the Issuer before updating to this version.
Failure to do so will result in users unable to login, or Jenkins failing to start.

[!CAUTION]
if using manual configuration and a JWKS Server URL has not been specified then either disable token validation will need to be enabled the JWKS Server URL will need to be set before upgrading to this version.
Failure to do so will result in users unable to login.

[!WARNING]
The option to send the scopes when requesting the access token has been removed (although is still present in the UI). Users of non conformant OPs that require this functionality should remain on the previous version until the Open ID Connect Originating Party (often referred to as the iDP) fixes their implementation.

So I attempted to make the required changes in my config code. This is the config that is currently working for v4.355.

  securityRealm:
    oic:
      serverConfiguration:
        wellKnown:
          wellKnownOpenIDConfigurationUrl: "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxxxxx/.well-known/openid-configuration"
      serverConfiguration:
        manual:
          authorizationServerUrl: "<myURL>/oauth2/authorize"
          scopes: "phone openid profile email"
          tokenServerUrl: "<myURL>/oauth2/token"
          userInfoServerUrl: "<myURL>/oauth2/userInfo"
      disableSslVerification: false
      escapeHatchEnabled: false
      logoutFromOpenidProvider: true
      userNameField: "username"
      clientId: "xxxxxxxxxxxxxxxxxxx"
      clientSecret: "COGNITO_CLIENT_SECRET"

The release notes indicated that I needed to add issuer so I did that with this code:

  securityRealm:
    oic:
      serverConfiguration:
        wellKnown:
          wellKnownOpenIDConfigurationUrl: "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxxxxx/.well-known/openid-configuration"
      serverConfiguration:
        manual:
          authorizationServerUrl: "<myURL>/oauth2/authorize"
          issuer: "<myURL>/oauth2/"
          scopes: "phone openid profile email"
          tokenServerUrl: "<myURL>/oauth2/token"
          userInfoServerUrl: "<myURL>/oauth2/userInfo"
      disableSslVerification: false
      escapeHatchEnabled: false
      logoutFromOpenidProvider: true
      userNameField: "username"
      clientId: "xxxxxxxxxxxxxxxxxxx"
      clientSecret: "COGNITO_CLIENT_SECRET"

This gets me past the 503 error but fails to authenticate with an error saying:

A problem occurred while processing the request

Logging ID=db1b7bda-ea4a-4577-a488-124b265417f7

So I went back to the jenkins log and found this error:

2024-10-14 18:34:00.917+0000 [id=15]    WARNING h.i.i.InstallUncaughtExceptionHandler#handleException: Caught unhandled exception with ID db1b7bda-ea4a-4577-a488-124b265417f7
java.lang.NullPointerException: Cannot invoke "java.net.URI.toURL()" because the return value of "com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata.getJWKSetURI()" is null

Another look at the notes mentions adding jwksServerUrl or disabling something. The part about disabling is unclear so I tried adding the jwksServerUrl like this:

  securityRealm:
    oic:
      serverConfiguration:
        wellKnown:
          wellKnownOpenIDConfigurationUrl: "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxxxxx/.well-known/openid-configuration"
      serverConfiguration:
        manual:
          authorizationServerUrl: "<myURL>/oauth2/authorize"
          issuer: "<myURL>/oauth2/"
          jwksServerUrl: "<myURL>/oauth2/jwks"
          scopes: "phone openid profile email"
          tokenServerUrl: "<myURL>/oauth2/token"
          userInfoServerUrl: "<myURL>/oauth2/userInfo"
      disableSslVerification: false
      escapeHatchEnabled: false
      logoutFromOpenidProvider: true
      userNameField: "username"
      clientId: "xxxxxxxxxxxxxxxxxxx"
      clientSecret: "COGNITO_CLIENT_SECRET"

This resulted in this error in the jenkins log

2024-10-14 18:49:30.200+0000 [id=15]    WARNING h.i.i.InstallUncaughtExceptionHandler#handleException: Caught unhandled exception with ID 1ddeb565-9360-447d-a839-4b45ffb52e06
org.pac4j.core.exception.TechnicalException: State cannot be determined

I attempted the disable piece of the notes by adding disableTokenValidation=true to my config only to discover that it was not a valid attribute.

Expected Results

Not having Jenkins crashing and to also complete the authentication process so I can run jobs.

Actual Results

I have pasted snippets from the errors that I received initially and also while attempting to update my config to make it work. I have currently pinned to v4.355 as it is working but I'd like to be able to upgrade to the latest versions of the plugin to pickup the security fixes etc.

Anything else?

No response

Are you interested in contributing a fix?

No response

PiersRBME commented 2 days ago

Hey, I happen to be doing something very similar - integrating Cognito with this plugin.

I tried the fully automated approach using the "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxxxxx/.well-known/openid-configuration" type of URL but it didn't work and I didn't have time to troubleshoot, so I have gone down the manual route.

I don't know what it means to the plugin to have both "manual" and "wellKnown" configuration in the same CasC - probably it's just picking one. I have simply the "manual" side.

One thing to note is if you have set up a custom domain name (don't know if you have), the JWKS endpoint is not on that custom domain name, it's at https://cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxxxxx/.well-known/jwks.json (Same thing applies to the new "Issuer" field, it uses the cognito-idp... domain.)

Hope that's of some help - I'm just another user like yourself, not part of the devs for this plugin.

sharpjl commented 2 days ago

@PiersRBME Thank you so much for your comment. I updated the issuer and jwksServerUrl settings to use the cognito domain and it is working.

jtnord commented 5 hours ago

The release notes was missing an "or,” which I have now added.

@sharpjl Could you let me know if this addresses your concern that they where not understandable.

if using manual configuration and a JWKS Server URL has not been specified then either disable token validation will need to be enabled or the JWKS Server URL will need to be set before upgrading to this version. Failure to do so will result in users unable to login

You either need a jwksServerUrl or you are not caring about validation of the token in which case you need to explicitly disable this (as you should always opt out of security, never in)

I don't know what it means to the plugin to have both "manual" and "wellKnown" configuration in the same CasC - probably it's just picking one. I have simply the "manual" side

It's invalid. I am amazed that CasC doesn't error, it really should do as the option is a single choice. You should choose one or the other and delete the obsolete one from your configuration.

Would you care to raise an issue in the configuration-as-code plugin for this?