Stream: troubleshooting

Topic: โœ” exchangeCodeForToken


view this post on Zulip Mohsen Jafari (Mar 11 2024 at 08:47):

I have my OpenID provider running. I have also my dockerized dataverse running. I set the OpenID jvm options and see the OpenID button in the dataverse login view. My authorize endpoint is called properly but my token endpoint is not called at all.

The following is the output of the .well-know/openid-configuration endpoint:

{
"issuer": "http://host.docker.internal:3000/api/auth",
"authorization_endpoint": "http://host.docker.internal:3000/api/auth/authorize",
"token_endpoint": "http://host.docker.internal:3000/api/auth/oauth-access-token",
"userinfo_endpoint": "http://host.docker.internal:3000/api/auth/oauth-user-profile",
"jwks_uri": "http://host.docker.internal:3000/api/auth/.well-known/jwks.json",
"response_types_supported": ["code", "token", "id_token", "code id_token"],
"subject_types_supported": ["public", "pairwise"],
"id_token_signing_alg_values_supported": ["RS256", "ES256", "HS256"]
}

And this is the log I see in the dataverse container logs:

[#|2024-03-11T08:35:03.773+0000|WARNING|Payara 6.2023.8|jakarta.enterprise.resource.webcontainer.faces.lifecycle|_ThreadID=76;_ThreadName=http-thread-pool::http-listener-1(1);_TimeMillis=1710146103773;_LevelValue=900;|
dataverse | #{OAuth2Page.exchangeCodeForToken()}: /oauth2/callback.xhtml @14,74 action="#{OAuth2Page.exchangeCodeForToken()}": java.net.ConnectException: Connection refused
dataverse | jakarta.faces.FacesException: #{OAuth2Page.exchangeCodeForToken()}: /oauth2/callback.xhtml @14,74 action="#{OAuth2Page.exchangeCodeForToken()}": java.net.ConnectException: Connection refused
dataverse | at com.sun.faces.application.ActionListenerImpl.getNavigationOutcome(ActionListenerImpl.java:83)
dataverse | at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:62)
dataverse | at jakarta.faces.component.UIViewAction.broadcast(UIViewAction.java:506)
dataverse | at jakarta.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:858)
dataverse | at jakarta.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1332)
dataverse | at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:56)
dataverse | at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:72)
dataverse | at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:159)
dataverse | at jakarta.faces.webapp.FacesServlet.executeLifecyle(FacesServlet.java:691)
dataverse | at jakarta.faces.webapp.FacesServlet.service(FacesServlet.java:449)
dataverse | at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1554)
dataverse | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:331)
dataverse | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:211)
dataverse | at org.glassfish.tyrus.servlet.TyrusServletFilter.doFilter(TyrusServletFilter.java:83)
dataverse | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:253)
dataverse | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:211)
dataverse | at org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(RewriteFilter.java:226)
dataverse | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:253)
dataverse | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:211)
dataverse | at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:257)
dataverse | at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:166)
dataverse | at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:757)
dataverse | at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:577)
dataverse | at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
dataverse | at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:158)
dataverse | at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:372)
dataverse | at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:239)
dataverse | at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:520)
dataverse | at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:217)
dataverse | at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:174)
dataverse | at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:153)
dataverse | at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:196)
dataverse | at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:88)
dataverse | at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:246)
dataverse | at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:178)
dataverse | at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:118)
dataverse | at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:96)
dataverse | at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:51)
dataverse | at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:510)
dataverse | at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:82)
dataverse | at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:83)
dataverse | at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:101)
dataverse | at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:535)
dataverse | at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:515)
dataverse | at java.base/java.lang.Thread.run(Unknown Source)
dataverse | Caused by: jakarta.el.ELException: /oauth2/callback.xhtml @14,74 action="#{OAuth2Page.exchangeCodeForToken()}": java.net.ConnectException: Connection refused
dataverse | at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:76)
dataverse | at com.sun.faces.application.ActionListenerImpl.getNavigationOutcome(ActionListenerImpl.java:74)
dataverse | ... 44 more
dataverse | Caused by: java.net.ConnectException: Connection refused
dataverse | at java.base/sun.nio.ch.Net.connect0(Native Method)
dataverse | at java.base/sun.nio.ch.Net.connect(Unknown Source)
dataverse | at java.base/sun.nio.ch.Net.connect(Unknown Source)
dataverse | at java.base/sun.nio.ch.NioSocketImpl.connect(Unknown Source)
dataverse | at java.base/java.net.Socket.connect(Unknown Source)
dataverse | at java.base/sun.net.NetworkClient.doConnect(Unknown Source)
dataverse | at java.base/sun.net.www.http.HttpClient.openServer(Unknown Source)
dataverse | at java.base/sun.net.www.http.HttpClient.openServer(Unknown Source)
dataverse | at java.base/sun.net.www.http.HttpClient.<init>(Unknown Source)
dataverse | at java.base/sun.net.www.http.HttpClient.New(Unknown Source)
dataverse | at java.base/sun.net.www.http.HttpClient.New(Unknown Source)
dataverse | at java.base/sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(Unknown Source)
dataverse | at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect0(Unknown Source)
dataverse | at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
dataverse | at java.base/sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source)
dataverse | at java.base/sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(Unknown Source)
dataverse | at java.base/sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
dataverse | at com.nimbusds.oauth2.sdk.http.HTTPRequest.toHttpURLConnection(HTTPRequest.java:939)
dataverse | at com.nimbusds.oauth2.sdk.http.HTTPRequest.send(HTTPRequest.java:1007)
dataverse | at edu.harvard.iq.dataverse.authorization.providers.oauth2.oidc.OIDCAuthProvider.getAccessToken(OIDCAuthProvider.java:268)
dataverse | at edu.harvard.iq.dataverse.authorization.providers.oauth2.oidc.OIDCAuthProvider.getUserRecord(OIDCAuthProvider.java:223)
dataverse | at edu.harvard.iq.dataverse.authorization.providers.oauth2.OAuth2LoginBackingBean.exchangeCodeForToken(OAuth2LoginBackingBean.java:103)
dataverse | at edu.harvard.iq.dataverse.authorization.providers.oauth2.OAuth2LoginBackingBean$Proxy$_$$_WeldSubclass.exchangeCodeForToken(Unknown Source)
dataverse | at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
dataverse | at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
dataverse | at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
dataverse | at java.base/java.lang.reflect.Method.invoke(Unknown Source)
dataverse | at jakarta.el.ELUtil.invokeMethod(ELUtil.java:227)
dataverse | at jakarta.el.BeanELResolver.invoke(BeanELResolver.java:481)
dataverse | at jakarta.el.CompositeELResolver.invoke(CompositeELResolver.java:198)...

view this post on Zulip Philip Durbin ๐Ÿš€ (Mar 11 2024 at 11:18):

Which Docker image are you using? The one called "alpha", which is 6.1 right now? Or "unstable", which is the "develop" branch?

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 11:30):

Philip Durbin said:

Which Docker image are you using? The one called "alpha", which is 6.1 right now? Or "unstable", which is the "develop" branch?

The following is my compose.yml:

version: "2.4"

services:

dataverse:
container_name: "dataverse"
hostname: dataverse
image: gdcc/dataverse:alpha
restart: on-failure
user: payara
environment:
_CT_DATAVERSE_SITEURL: "http://localhost:8080"
DATAVERSE_DB_HOST: postgres
DATAVERSE_DB_PASSWORD: secret
DATAVERSE_DB_USER: dataverse
DATAVERSE_FEATURE_API_BEARER_AUTH: "1"
JVM_ARGS: -Ddataverse.files.storage-driver-id=file1
-Ddataverse.files.file1.type=file
-Ddataverse.files.file1.label=Filesystem
-Ddataverse.files.file1.directory=${STORAGE_DIR}/store
-Ddataverse.pid.providers=fake
-Ddataverse.pid.default-provider=fake
-Ddataverse.pid.fake.type=FAKE
-Ddataverse.pid.fake.label=FakeDOIProvider
-Ddataverse.pid.fake.authority=10.5072
-Ddataverse.pid.fake.shoulder=FK2/
-Ddataverse.auth.oidc.enabled=true
-Ddataverse.auth.oidc.client-id=some_id
-Ddataverse.auth.oidc.client-secret=some_secret
-Ddataverse.auth.oidc.auth-server-url=http://host.docker.internal:3000/api/auth/
-Ddataverse.auth.oidc.title=OpenID
ports:

  - "8080:8080" # HTTP (Dataverse Application)
  - "4848:4848" # HTTP (Payara Admin Console)
  - "9009:9009" # JDWP
  - "8686:8686" # JMX
networks:

  - dataverse
depends_on:

  - postgres
  - solr
  - dv_initializer
volumes:

  - ./data/app/data:/dv
  - ./data/app/secrets:/secrets
tmpfs:

  - /dumps:mode=770,size=2052M,uid=1000,gid=1000
  - /tmp:mode=770,size=2052M,uid=1000,gid=1000
mem_limit: 2147483648 # 2 GiB
mem_reservation: 1024m
privileged: false

bootstrap:
container_name: "bootstrap"
image: gdcc/configbaker:alpha
restart: "no"
command:

  - bootstrap.sh
  - dev
  #- demo
#volumes:
#  - ./demo:/scripts/bootstrap/demo
networks:

  - dataverse

dv_initializer:
container_name: "dv_initializer"
image: gdcc/configbaker:alpha
restart: "no"
command:

  - sh
  - -c
  - "fix-fs-perms.sh dv"
volumes:

  - ./data/app/data:/dv

postgres:
container_name: "postgres"
hostname: postgres
image: postgres:13
restart: on-failure
environment:

  - POSTGRES_USER=dataverse
  - POSTGRES_PASSWORD=secret
ports:

  - "5432:5432"
networks:

  - dataverse
volumes:

  - ./data/postgresql/data:/var/lib/postgresql/data

solr_initializer:
container_name: "solr_initializer"
image: gdcc/configbaker:alpha
restart: "no"
command:

  - sh
  - -c
  - "fix-fs-perms.sh solr && cp -a /template/* /solr-template"
volumes:

  - ./data/solr/data:/var/solr
  - ./data/solr/conf:/solr-template

solr:
container_name: "solr"
hostname: "solr"
image: solr:9.3.0
depends_on:

  - solr_initializer
restart: on-failure
ports:

  - "8983:8983"
networks:

  - dataverse
command:

  - "solr-precreate"
  - "collection1"
  - "/template"
volumes:

  - ./data/solr/data:/var/solr
  - ./data/solr/conf:/template

smtp:
container_name: "smtp"
hostname: "smtp"
image: maildev/maildev:2.0.5
restart: on-failure
ports:

  - "25:25" # smtp server
  - "1080:1080" # web ui
environment:

  - MAILDEV_SMTP_PORT=25
  - MAILDEV_MAIL_DIRECTORY=/mail
networks:

  - dataverse
#volumes:
#  - ./data/smtp/data:/mail
tmpfs:

  - /mail:mode=770,size=128M,uid=1000,gid=1000

networks:
dataverse:
driver: bridge

view this post on Zulip Philip Durbin ๐Ÿš€ (Mar 11 2024 at 12:08):

Ok, "alpha", thanks. So 6.1.

view this post on Zulip Philip Durbin ๐Ÿš€ (Mar 11 2024 at 12:09):

Can you reach http://host.docker.internal:3000/api/auth from the Dataverse container? With curl or whatever?

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 12:15):

Philip Durbin said:

Can you reach http://host.docker.internal:3000/api/auth from the Dataverse container? With curl or whatever?

But The http://host.docker.internal:3000/api/auth is my OpenID Provider's auth controller and not any specific endpoint within it.

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 12:17):

But if I call any specific endpoint of the auth controller from within the dataverse they are called. For example the following is the result of the http://host.docker.internal:3000/api/auth/.well-known/openid-configuration endpoint:

{"issuer":"http://host.docker.internal:3000/api/auth","authorization_endpoint":"http://localhost:3000/api/auth/authorize","token_endpoint":"http://host.docker.internal:3000/api/auth/oauth-access-token","userinfo_endpoint":"http://host.docker.internal:3000/api/auth/oauth-user-profile","jwks_uri":"http://host.docker.internal:3000/api/auth/.well-known/jwks.json","response_types_supported":["code","token","id_token","code id_token"],"subject_types_supported":["public","pairwise"],"id_token_signing_alg_values_supported":["RS256","ES256","HS256"]}

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:04):

I see Connection refused for edu.harvard.iq.dataverse.authorization.providers.oauth2.oidc.OIDCAuthProvider.getAccessToken(OIDCAuthProvider.java:268. That line is specifically the point where Dataverse reaches out to the token endpoint.

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:06):

Yes, but I don't know what endpoint exactly it is trying to call. I think all my configs are fine (as shown above).

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:06):

Seeing this "connection refused" might either be a connection problem between Dataverse and the provider or an invalid secret thing.

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:07):

If you use docker exec to open a shell in your container, can you try to reachout to the URL given in the token endpoint?

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:07):

Just to make sure it's not DNS getting in our way

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:08):

(I've seen very weird DNS issues lately with alpine glibc/musl images, but this is an Ubuntu based image so we should be fine with DNS resolvers)

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:09):

mohsen@Mohsens-Air % docker exec -it dataverse sh
$ curl -X POST http://host.docker.internal:3000/api/auth/oauth-access-token
{"statusCode":401,"message":"Unauthorized"}$

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:09):

The exec could be something like docker exec -it dataverse-1 curl "http://host.docker.internal:3000/api/auth/oauth-access-token"

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:10):

The above is the call.

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:11):

OK that's something! Looks like Dataverse can talk to the endpoint! Great!

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:13):

Did you enable PKCE? (This is not yet very battle tested and might cause problems, checking to potentially rule it out)

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:14):

I don't know how to enable or disable PKCE.

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:14):

That would be JVM options

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:15):

See https://guides.dataverse.org/en/latest/installation/oidc.html#provision-via-jvm-options

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:16):

Just to double check: does your OIDC provider work without PKCE enabled? (Asking because some providers explicitely require you to enable PKCE)

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:16):

But as you can see in the above compose.yml, I didn't set any PKCE to true.

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:16):

I personally implemented the OpenID Provider and I did not implement the PKCE part, yet.

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:17):

Oha! A custom OIDC provider! Fancy that!

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:17):

I took some time to implement it using NestJS.

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:17):

OK at this point I would either go for tcpdump + Wireshark to take a look at the packages being exchanged and/or use a Debugger to see what's going on inside

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:18):

Could you give me a clue on the Debugger approach, so I can follow it.

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:18):

Of course. Just a moment

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:19):

Do you have a Java IDE around?

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:19):

I have VSCode in my MacBook.

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:20):

OK never used VSCode with a Java debugger, but I suppose there will be docs online to use it.

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:20):

I will check.

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:20):

You will need to checkout the v6.1 codebase https://github.com/IQSS/dataverse/tree/v6.1

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:21):

Please add option as suggested in the container docs: https://guides.dataverse.org/en/latest/container/dev-usage.html#using-a-debugger

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:21):

Then you can use the debugger in your IDE to set breaking points and attach it to the running JVM process

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:22):

Upon trying the login, the breaking point will be triggered and the debugger should kick in

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:23):

Thank you so much Oliver

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:23):

No worries! I'm the one who built in any errors and bugs, so happy to help :wink:

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:25):

We definetly should add a try/catch there to add some more helpful log output than just forwarding the exception :see_no_evil:

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:25):

Exactly

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:26):

This might be helpful: https://code.visualstudio.com/docs/java/java-debugging

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:27):

I will check it.

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:28):

This answer looks helpful, too, as the docs are mostly about running + debug - but we want to attach to a running JVM. https://stackoverflow.com/a/53389655

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:29):

Sure

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:29):

Note the https://code.visualstudio.com/docs/java/java-debugging#_hot-code-replace

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:30):

You might be able to alter the running code in the JVM this way to add this try/catch block or add other specifics

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:30):

Yeah

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:32):

Do you know what HTTP method does dataverse use when calling the token endpoint?

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:34):

POST

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:34):

HTTPRequest httpRequest = new HTTPRequest(Method.POST, this.getEndpointURI()); from TokenRequest.class in Nimbus SDK

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:35):

Again, a first easy step might be dumping the traffic via tcpdump and look at the packages using Wireshark

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:37):

And, in the codebase, I see a bunch of isDebug() to log/not log helpful information. Can it be set using an environment variable so the isDebug() returns true, making logs to the container logs?

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:45):

Sorry where do you see those? rg -i "isDebug" src/main/java gives me nothing?

view this post on Zulip Mohsen Jafari (Mar 11 2024 at 13:47):

OAuth20Service.class

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:49):

Sounds like Scribus SDK

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:49):

That is beyond our control and not used for OIDC

view this post on Zulip Oliver Bertuch (Mar 11 2024 at 13:49):

OIDC uses Nimbus SDK https://connect2id.com/products/nimbus-oauth-openid-connect-sdk

view this post on Zulip Mohsen Jafari (Mar 12 2024 at 12:11):

I put some logging middleware in my OIDC side so that I understood the problem. My token endpoint expects these four items to be received from dataverse when calling token endpoint:

client_id
client_secret
redirect_uri
code

However, the dataverse is sending the following data when calling my token endpoint:

code
redirect_uri
grant_type
scope

view this post on Zulip Mohsen Jafari (Mar 12 2024 at 12:12):

I updated my message.

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:12):

Huh? Why are you expecting the client_id and secret?

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:14):

https://openid.net/specs/openid-connect-core-1_0.html#TokenRequest

view this post on Zulip Mohsen Jafari (Mar 12 2024 at 12:14):

I thought authorization code and redirect_uri wouldn't be enough as security perspective.

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:15):

Implementations will likely stick to the spec and not add extras :see_no_evil:

view this post on Zulip Mohsen Jafari (Mar 12 2024 at 12:15):

Thanks

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:18):

I see "If the Client is a Confidential Client, then it MUST authenticate to the Token Endpoint using the authentication method registered for its client_id, as described in Section 9" in there.

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:18):

What kind of authentication methods do you support for confidential clients?

view this post on Zulip Mohsen Jafari (Mar 12 2024 at 12:19):

To be honest, I never thought of a confidential client at all in my OIDC.

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:19):

You can require a confidential client to present its client_id and client_secret

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:20):

With non-confidential / public clients, you can't :grinning:

view this post on Zulip Mohsen Jafari (Mar 12 2024 at 12:20):

You mean I can configure the dataverse so that it also sends the client_id and secret when calling token endpoint?

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:21):

Actually I think this should already happen

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:22):

As in "supposed to happen"

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:22):

From "new TokenRequest(this.idpMetadata.getTokenEndpointURI(), this.clientAuth,..." it's already clear that the request has the confidential information (this.clientAuth)

view this post on Zulip Mohsen Jafari (Mar 12 2024 at 12:24):

This is the whole body of the dataverse request towards my token endpoint:

Body: {"code":"123456789","redirect_uri":"http://some_IP:8080/oauth2/callback.xhtml","grant_type":"authorization_code","scope":"openid email profile"}

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:24):

Sorry I forgot: have you configured the confidential secrets?

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:25):

From what I see in the code, this _should_ work already and include these details.

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:25):

Oh oh oh wait

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:25):

We're using "ClientSecretBasic".

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:26):

That one sets the secrets as Authorization HTTP header

view this post on Zulip Mohsen Jafari (Mar 12 2024 at 12:26):

I only set the following in domain.xml

<jvm-options>-Ddataverse.auth.oidc.enabled=true</jvm-options>
<jvm-options>-Ddataverse.auth.oidc.client-id=some_id</jvm-options>
<jvm-options>-Ddataverse.auth.oidc.client-secret=some_secret</jvm-options>
<jvm-options>-Ddataverse.auth.oidc.auth-server-url=https://my.domain.com/api/auth/</jvm-options>
<jvm-options>-Ddataverse.auth.oidc.title=OpenID</jvm-options>

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:26):

Could you check the headers if they are present?

view this post on Zulip Mohsen Jafari (Mar 12 2024 at 12:26):

Yes

view this post on Zulip Mohsen Jafari (Mar 12 2024 at 12:27):

Headers: {"x-real-ip":"some_ip","x-forwarded-for":"some_ip, some_ip","host":"my.example.com","x-nginx-proxy":"true","connection":"close","content-length":"172","authorization":"Basic YzdjZGE5NjgtNWM3Mi00NTg1LTlmOGEtNWQ4NjBlNzFhNzE2OmJjM2RhMWNjMTY2MGIxMTRiNDA4ZThiNTJmYzM0OThmZDJlMDI4ZDg5MmJkMGMyMTc5MzhmZjBlNmIxMzNkYjU=","content-type":"application/x-www-form-urlencoded; charset=UTF-8","user-agent":"Java/17.0.10","accept":"text/html, image/gif, image/jpeg, *; q=.2, /; q=.2"}

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:27):

Ha there we go!

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:28):

Quoting from the OIDC spec:
"client_secret_basic
Clients that have received a client_secret value from the Authorization Server authenticate with the Authorization Server in accordance with Section 2.3.1 of OAuth 2.0 [RFC6749] using the HTTP Basic authentication scheme. "

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:28):

https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:29):

So you could say your confidential clients are only allowed to use the post method (quote: "including the Client Credentials in the request body"), which would indeed need an extension of Dataverse to make people select the method to be used

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:32):

Doing that should be simple: this constructor for the provider needs to be changed:

public OIDCAuthProvider(String aClientId, String aClientSecret, String issuerEndpointURL,
                            boolean pkceEnabled, String pkceMethod) throws AuthorizationSetupException {
        this.clientSecret = aClientSecret; // nedded for state creation
        this.clientAuth = new ClientSecretBasic(new ClientID(aClientId), new Secret(aClientSecret));

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:33):

This would need a distinction which method to use and act accordingly (different classes)

view this post on Zulip Mohsen Jafari (Mar 12 2024 at 12:34):

Was I in the wrong path when implementing my OIDC that now need to modify the dataverse's codebase, OR this is usual?

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:35):

Yes and no

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:35):

It seems to me you have only implemented one option of client auth methods

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:36):

The HTTP Basic Auth theme is pretty common as far as I know. I'm not aware of a provider not supporting it.

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:36):

These are design decisions you have to make.

view this post on Zulip Mohsen Jafari (Mar 12 2024 at 12:37):

So updating my OIDC provider to support it would make more sense, compared to touching the dataverse side.

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:37):

We would be glad to accept a pull request extending Dataverse. There even are integration tests in place using Keycloak, so it would be easy to get you started.

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:37):

That said, if you are looking for quick results and want to be more compatible with clients, it probably is a good idea to add HTTP basic auth support to your provider

view this post on Zulip Mohsen Jafari (Mar 12 2024 at 12:39):

I have to discuss with my team lead and decide what to do. Anyway, thank you so much for your help.

view this post on Zulip Notification Bot (Mar 12 2024 at 12:39):

Mohsen Jafari has marked this topic as resolved.

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:39):

No worries! That's what we're here for. I am going ahead and mark this topic as resolved. If you opt for developing a patch for Dataverse, please create a new topic over at the #dev stream, thx!

view this post on Zulip Oliver Bertuch (Mar 12 2024 at 12:40):

You beat me to it :smile_cat:


Last updated: Oct 30 2025 at 06:21 UTC