tchiotludo / akhq

Kafka GUI for Apache Kafka to manage topics, topics data, consumers group, schema registry, connect and more...
https://akhq.io/
Apache License 2.0
3.41k stars 661 forks source link

OICD Login redirects to http, resulting in invalid_grant error #1666

Open mat-patrickschmelter opened 9 months ago

mat-patrickschmelter commented 9 months ago

When trying to log in using a keycloak oidc provider, the first login succeeds. After waiting a few hours, the session gets invalid but cannot be closed correctly as it seems (by the way, even pressing logout will not end the session - thats another bug which cloud be related?). After pressing login again, the callback uri will be opened using http instead of https. After accepting the warning message in the browser, I get redirected to the https endpoint, reulting in the following error message:

"message":"Internal Server Error: error: invalid_grant, errorDescription: Code not valid, errorUri: null","_links":{"self":{"href":"/oauth/callback/oidc?state=__STATE__%3D&session_state=____&code=____","templated":false}},"_embedded":{"stacktrace":[{"message":"io.micronaut.http.client.exceptions.HttpClientResponseException: error: invalid_grant, errorDescription: Code not valid, errorUri: null
io.micronaut.http.client.netty.DefaultHttpClient$FullHttpResponseHandler.makeErrorFromRequestBody(DefaultHttpClient.java:2240)
io.micronaut.http.client.netty.DefaultHttpClient$FullHttpResponseHandler.forwardResponseToPromise(DefaultHttpClient.java:2202)
io.micronaut.http.client.netty.DefaultHttpClient$FullHttpResponseHandler.channelReadInstrumented(DefaultHttpClient.java:2171)
io.micronaut.http.client.netty.DefaultHttpClient$FullHttpResponseHandler.channelReadInstrumented(DefaultHttpClient.java:2139)
io.micronaut.http.client.netty.SimpleChannelInboundHandlerInstrumented.channelRead0(SimpleChannelInboundHandlerInstrumented.java:46)
io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346)
io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318)
io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1475)
io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1338)
io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1387)
io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:529)
io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:468)
io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93)
io.micronaut.http.client.netty.ResettableReadTimeoutHandler$NextInterceptor.channelRead(ResettableReadTimeoutHandler.java:92)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
io.micronaut.http.client.netty.ResettableReadTimeoutHandler.channelRead(ResettableReadTimeoutHandler.java:64)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
java.base/java.lang.Thread.run(Unknown Source)
"}]}

AKHQ Config:

micronaut:
  server:
    port: 5000
    access-log:
      enabled: true
      name: org.akhq.log.access
    netty:
      max-header-size: 16384
  security:
    enabled: true
    callback-uri: "https://some.url/oauth/callback/oidc"
    oauth2:
      enabled: true
      clients:
        oidc:
          client-id: client_id
          client-secret: client_secret
          openid:
            issuer: issuer_url
    token:
      jwt:
        signatures:
          secret:
            generator:
              secret: jwt_secret
              jws-algorithm: HS256
  http:
    client:
      allow-block-event-loop: true

endpoints:
  health:
    url:
      enabled: true
    enabled: true
    sensitive: false
    details-visible: ANONYMOUS

logger:
  levels:
    io.micronaut.security: TRACE

akhq:
  security:
    default-group: no-roles
    rest:
      enabled: true
      url: role_mapper_uri
    oidc:
      enabled: true
      providers:
        oidc:
          label: "Login"
          username-field: email
          groups-field: roles
          default-group: default
    [OTHER IRRELEVANT CONFIG]

Trace Logs: https://pastebin.com/9q8wgDCX

TigranKhudav commented 8 months ago

Hi @mat-patrickschmelter did you find this solution? @tchiotludo can you help?

mat-patrickschmelter commented 8 months ago

The problem still exists

AlexisSouquiere commented 8 months ago

Can you check this and see if updating the Keycloak configuration solves the issue ?

I don't know what could cause the issue on the AKHQ side as it seems to be deeply linked to the auth flow between micronaut and keycloak.

If it doesn't work, can you increase the logs to TRACE ? We will have more information about this auth flow

qkhuyit commented 8 months ago

I have same isssue

MaybeIknow commented 8 months ago

Hello @AlexisSouquiere Patrick is not in at the moment, but we will check for the logs and reach out to you again

marcosschroh commented 8 months ago

Same issue

AlexisSouquiere commented 8 months ago

Can you check this and see if updating the Keycloak configuration solves the issue ?

I don't know what could cause the issue on the AKHQ side as it seems to be deeply linked to the auth flow between micronaut and keycloak.

If it doesn't work, can you increase the logs to TRACE ? We will have more information about this auth flow

@qkhuyit, @marcosschroh please check my message above, try the possible fix from the Keycloak config and give more logs if it doesn't work

mat-patrickschmelter commented 7 months ago

We still encounter the same issue after applying the changes you suggested to our keycloak. I will attach two log exports with trace logging enabled.

In the first case, the user sees an error message in the browser with the stacktrace including errorcode "invalid_grant". A workaround is to refresh the browser window - inclucing cache, and the user will be logged in https://pastebin.com/D0dgJEPK

The second case redirects the user to the /login/failed url, which leads to an endless loop if the user clicks "Login" again. Refreshing the page does not solve the problem. After some time the error disappears and the user is able to log in normally https://pastebin.com/nhgk58aZ

MaybeIknow commented 6 months ago

hi @AlexisSouquiere, the problem is still occurring. is there anything new here yet? many thanks in advance

mat-patrickschmelter commented 6 months ago

@MaybeIknow is part of our team.

Any news on this Issue yet? We experience this problem since the beginning of the year and our users are slowly getting kind of nervous :)

marcosschroh commented 6 months ago

We moved to a different project, I really recommend http://ui.docs.kafbat.io/

AlexisSouquiere commented 6 months ago

@mat-patrickschmelter, @MaybeIknow did you had a look to this ? It seems that people already had this kind of issue and had to force https scheme in the callback uri

I'm also trying to reproduce it on my side. It should fix the http instead of https issue but I don't know if it will fix the invalid_grant issue

mat-patrickschmelter commented 6 months ago

We have implemented the suggested changes and will monitor the behavior for a few days

mat-patrickschmelter commented 5 months ago

@AlexisSouquiere unfortunately, the issue still exists

AlexisSouquiere commented 5 months ago

Do you still have the two issues ? I mean the callback uri call with http and the invalid_grant issue ? Or did the config update fix the first one ?

mat-patrickschmelter commented 5 months ago

Yes we still have both issues

TigranKhudav commented 4 months ago

I recommend use Kafbat https://github.com/kafbat/kafka-ui It is normally integrated with Keycloak