Open
Description
I’m trying to set up OAuth2 authentication for the Trino Web UI using Yandex ID as the provider. However, I’ve encountered an issue: Yandex’s /userinfo
endpoint does not provide the sub
field in its response (it uses id
instead). Despite setting principal-field=id
in the configuration, Trino’s OAuth2 implementation requires the sub
field due to its reliance on Nimbus OIDC’s UserInfoResponse, which enforces the presence of sub
.
Questions:
- Is this behavior intentional (strict
sub
requirement), or could Trino support alternative fields likeid
for non-OpenID providers? - Would this require a change in Trino’s OAuth2 client, or should it be addressed in the Nimbus SDK?
- Are there known workarounds (e.g., custom response parsing)? Maybe an HTTP proxy could help?
I’d appreciate any guidance on how to proceed. Thank you in advance.
Setup: Docker with Trino 470 (trinodb/trino:470
).
Current configuration:
web-ui.enabled=true
web-ui.authentication.type=OAUTH2
http-server.https.enabled=true
http-server.https.port=3443
http-server.authentication.oauth2.issuer=https://oauth.yandex.ru
http-server.authentication.oauth2.auth-url=https://oauth.yandex.ru/authorize
http-server.authentication.oauth2.token-url=https://oauth.yandex.ru/token
http-server.authentication.oauth2.jwks-url=https://oauth.yandex.ru/jwks
http-server.authentication.oauth2.userinfo-url=https://login.yandex.ru/info
http-server.authentication.oauth2.scopes=login:email
http-server.authentication.oauth2.principal-field=id
http-server.authentication.oauth2.client-id=${ENV:OAUTH2_CLIENT_ID}
http-server.authentication.oauth2.client-secret=${ENV:OAUTH2_CLIENT_SECRET}
http-server.authentication.oauth2.oidc.discovery=false
Error log:
2025-04-21T16:30:23.465Z INFO main io.trino.server.Server ======== SERVER STARTED ========
2025-04-21T16:31:10.393Z ERROR http-worker-197 io.trino.server.security.oauth2.NimbusAirliftHttpClient Received bad response from userinfo endpoint
java.lang.RuntimeException: Unable to parse response status=[200], body=[{"id": "***", "login": "dikuchan", "client_id": "***", "default_email": "dikuchan@***.ru", "emails": ["dikuchan@***.ru"], "psuid": "***"}]
at io.trino.server.security.oauth2.NimbusAirliftHttpClient$NimbusResponseHandler.handle(NimbusAirliftHttpClient.java:132)
at io.airlift.http.client.jetty.JettyHttpClient.doExecute(JettyHttpClient.java:774)
at io.airlift.http.client.jetty.JettyHttpClient.execute(JettyHttpClient.java:687)
at io.trino.server.security.oauth2.NimbusAirliftHttpClient.execute(NimbusAirliftHttpClient.java:101)
at io.trino.server.security.oauth2.NimbusOAuth2Client.queryUserInfo(NimbusOAuth2Client.java:400)
at io.trino.server.security.oauth2.NimbusOAuth2Client.getJWTClaimsSet(NimbusOAuth2Client.java:392)
at io.trino.server.security.oauth2.NimbusOAuth2Client$OAuth2AuthorizationCodeFlow.toResponse(NimbusOAuth2Client.java:259)
at io.trino.server.security.oauth2.NimbusOAuth2Client$OAuth2AuthorizationCodeFlow.getOAuth2Response(NimbusOAuth2Client.java:242)
at io.trino.server.security.oauth2.NimbusOAuth2Client.getOAuth2Response(NimbusOAuth2Client.java:177)
at io.trino.server.security.oauth2.OAuth2Service.finishOAuth2Challenge(OAuth2Service.java:173)
at io.trino.server.security.oauth2.OAuth2CallbackResource.callback(OAuth2CallbackResource.java:73)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:146)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:189)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:176)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:93)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:478)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:400)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:81)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:274)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:266)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:253)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:696)
at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:397)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:349)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:358)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:312)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)
at org.eclipse.jetty.ee10.servlet.ServletHolder.handle(ServletHolder.java:736)
at org.eclipse.jetty.ee10.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1619)
at io.airlift.http.server.tracing.TracingServletFilter.doFilter(TracingServletFilter.java:115)
at org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter(FilterHolder.java:205)
at org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1591)
at org.eclipse.jetty.ee10.servlet.ServletHandler$MappedServlet.handle(ServletHandler.java:1552)
at org.eclipse.jetty.ee10.servlet.ServletChannel.dispatch(ServletChannel.java:819)
at org.eclipse.jetty.ee10.servlet.ServletChannel.handle(ServletChannel.java:436)
at org.eclipse.jetty.ee10.servlet.ServletHandler.handle(ServletHandler.java:469)
at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:611)
at org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:1060)
at org.eclipse.jetty.server.Handler$Wrapper.handle(Handler.java:740)
at org.eclipse.jetty.server.handler.EventsHandler.handle(EventsHandler.java:81)
at org.eclipse.jetty.server.Server.handle(Server.java:182)
at org.eclipse.jetty.server.internal.HttpChannelState$HandlerInvoker.run(HttpChannelState.java:662)
at org.eclipse.jetty.util.thread.Invocable$ReadyTask.run(Invocable.java:175)
at org.eclipse.jetty.http2.server.internal.HttpStreamOverHTTP2$1.run(HttpStreamOverHTTP2.java:135)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:480)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:443)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:293)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.produce(AdaptiveExecutionStrategy.java:195)
at org.eclipse.jetty.http2.HTTP2Connection.produce(HTTP2Connection.java:209)
at org.eclipse.jetty.http2.HTTP2Connection.onFillable(HTTP2Connection.java:156)
at org.eclipse.jetty.http2.HTTP2Connection$FillableCallback.succeeded(HTTP2Connection.java:442)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:99)
at org.eclipse.jetty.io.ssl.SslConnection$SslEndPoint.onFillable(SslConnection.java:575)
at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:390)
at org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:150)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:99)
at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:480)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:443)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:293)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.run(AdaptiveExecutionStrategy.java:201)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:311)
at org.eclipse.jetty.util.thread.MonitoredQueuedThreadPool$1.run(MonitoredQueuedThreadPool.java:73)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:979)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1209)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1164)
at java.base/java.lang.Thread.run(Thread.java:1575)
Caused by: com.nimbusds.oauth2.sdk.ParseException: Couldn't parse UserInfo claims: Missing or invalid "sub" claim
at com.nimbusds.openid.connect.sdk.UserInfoSuccessResponse.parse(UserInfoSuccessResponse.java:228)
at com.nimbusds.openid.connect.sdk.UserInfoResponse.parse(UserInfoResponse.java:73)
at io.trino.server.security.oauth2.NimbusAirliftHttpClient$NimbusResponseHandler.handle(NimbusAirliftHttpClient.java:129)
... 74 more
Caused by: java.lang.IllegalArgumentException: Missing or invalid "sub" claim
at com.nimbusds.openid.connect.sdk.claims.UserInfo.<init>(UserInfo.java:120)
at com.nimbusds.openid.connect.sdk.UserInfoSuccessResponse.parse(UserInfoSuccessResponse.java:223)
... 76 more
2025-04-21T16:31:10.395Z DEBUG http-worker-197 io.trino.server.security.oauth2.OAuth2Service Authentication response could not be verified: state=***
io.trino.server.security.oauth2.ChallengeFailedException: invalid access token
at io.trino.server.security.oauth2.NimbusOAuth2Client$OAuth2AuthorizationCodeFlow.lambda$toResponse$0(NimbusOAuth2Client.java:259)
at java.base/java.util.Optional.orElseThrow(Optional.java:403)
at io.trino.server.security.oauth2.NimbusOAuth2Client$OAuth2AuthorizationCodeFlow.toResponse(NimbusOAuth2Client.java:259)
at io.trino.server.security.oauth2.NimbusOAuth2Client$OAuth2AuthorizationCodeFlow.getOAuth2Response(NimbusOAuth2Client.java:242)
at io.trino.server.security.oauth2.NimbusOAuth2Client.getOAuth2Response(NimbusOAuth2Client.java:177)
at io.trino.server.security.oauth2.OAuth2Service.finishOAuth2Challenge(OAuth2Service.java:173)
at io.trino.server.security.oauth2.OAuth2CallbackResource.callback(OAuth2CallbackResource.java:73)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:146)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:189)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:176)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:93)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:478)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:400)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:81)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:274)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:266)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:253)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:696)
at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:397)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:349)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:358)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:312)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)
at org.eclipse.jetty.ee10.servlet.ServletHolder.handle(ServletHolder.java:736)
at org.eclipse.jetty.ee10.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1619)
at io.airlift.http.server.tracing.TracingServletFilter.doFilter(TracingServletFilter.java:115)
at org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter(FilterHolder.java:205)
at org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1591)
at org.eclipse.jetty.ee10.servlet.ServletHandler$MappedServlet.handle(ServletHandler.java:1552)
at org.eclipse.jetty.ee10.servlet.ServletChannel.dispatch(ServletChannel.java:819)
at org.eclipse.jetty.ee10.servlet.ServletChannel.handle(ServletChannel.java:436)
at org.eclipse.jetty.ee10.servlet.ServletHandler.handle(ServletHandler.java:469)
at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:611)
at org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:1060)
at org.eclipse.jetty.server.Handler$Wrapper.handle(Handler.java:740)
at org.eclipse.jetty.server.handler.EventsHandler.handle(EventsHandler.java:81)
at org.eclipse.jetty.server.Server.handle(Server.java:182)
at org.eclipse.jetty.server.internal.HttpChannelState$HandlerInvoker.run(HttpChannelState.java:662)
at org.eclipse.jetty.util.thread.Invocable$ReadyTask.run(Invocable.java:175)
at org.eclipse.jetty.http2.server.internal.HttpStreamOverHTTP2$1.run(HttpStreamOverHTTP2.java:135)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:480)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:443)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:293)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.produce(AdaptiveExecutionStrategy.java:195)
at org.eclipse.jetty.http2.HTTP2Connection.produce(HTTP2Connection.java:209)
at org.eclipse.jetty.http2.HTTP2Connection.onFillable(HTTP2Connection.java:156)
at org.eclipse.jetty.http2.HTTP2Connection$FillableCallback.succeeded(HTTP2Connection.java:442)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:99)
at org.eclipse.jetty.io.ssl.SslConnection$SslEndPoint.onFillable(SslConnection.java:575)
at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:390)
at org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:150)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:99)
at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:480)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:443)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:293)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.run(AdaptiveExecutionStrategy.java:201)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:311)
at org.eclipse.jetty.util.thread.MonitoredQueuedThreadPool$1.run(MonitoredQueuedThreadPool.java:73)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:979)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1209)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1164)
at java.base/java.lang.Thread.run(Thread.java:1575)
Metadata
Metadata
Assignees
Labels
No labels