openanalytics / shinyproxy

ShinyProxy - Open Source Enterprise Deployment for Shiny and data science apps
https://www.shinyproxy.io
Apache License 2.0
525 stars 151 forks source link

Redirection to /auth_error by keycloak despite being logged in. #526

Closed Qnouro closed 1 week ago

Qnouro commented 2 months ago

Hello,

Context

We have a shinyproxy instance running alongside a keycloak instance. Sometimes (not always), when a user connects (successfully), it gets redirected to the /auth_error page. Refreshing or clicking on "Go back to the main page" redirects them to the shinyproxy homepage.

We aren't certain but we suspect that we may have a redirect loop as referred to in the documentation: https://www.shinyproxy.io/documentation/troubleshooting/#my-browser-reports-a-redirect-loop-when-using-openid-connect.

Shinyproxy version: 3.1.1 (we had the same issue in 3.1.0)

Logs:

Keycloak log:


2024-09-17 08:05:12,154 WARN  [org.keycloak.events] (executor-thread-632) type="RESTART_AUTHENTICATION_ERROR", realmId="my_realm_id", realmName="my_realm", clientId="shinyproxy", userId="null", ipAddress="10.0.0.2", error="already_logged_in", response_type="code", redirect_uri="[https://my_app.com/login/oauth2/code/shinyproxy"](https://my_app.com/login/oauth2/code/shinyproxy%22), redirected_to_client="true", response_mode="query"

Shinyproxy log:


2024-09-17T08:05:07.604573918Z INFO Initializing Spring DispatcherServlet 'dispatcherServlet' | @timestamp=2024-09-17T08:05:07.604190001Z @version=1 logger_name=io.undertow.servlet thread_name=XNIO-1 task-2 level_value=20000

2024-09-17T08:05:07.604765895Z INFO Initializing Servlet 'dispatcherServlet' | @timestamp=2024-09-17T08:05:07.604677388Z @version=1 logger_name=o.s.web.servlet.DispatcherServlet thread_name=XNIO-1 task-2 level_value=20000

2024-09-17T08:05:07.606882550Z INFO Completed initialization in 2 ms | @timestamp=2024-09-17T08:05:07.606776342Z @version=1 logger_name=o.s.web.servlet.DispatcherServlet thread_name=XNIO-1 task-2 level_value=20000

2024-09-17T08:05:11.947004461Z INFO User logged in [user: my_username] | @timestamp=2024-09-17T08:05:11.946803639Z @version=1 logger_name=e.o.containerproxy.service.UserService thread_name=XNIO-1 task-2 level_value=20000

2024-09-17T08:05:12.169331558Z ERROR org.springframework.security.oauth2.core.OAuth2AuthenticationException: [authorization_request_not_found] | @timestamp=2024-09-17T08:05:12.169103017Z @version=1 logger_name=e.o.c.a.impl.OpenIDAuthenticationBackend thread_name=XNIO-1 task-3 level_value=40000

How to reproduce

The error is hard to reproduce and, in the same conditions, doesn't always happen.

It however seems to happen in the following scenario:

Please note that when clicking on "Go back to the main page", the user is redirected to the homepage and is effectively already logged in. We can also see in the shinyproxy logs that the user has been logged in before the error is raised (instantly afterwards).

Potential tracks

Some tracks we have:

logging:
  file:
    name: /var/log/shinyproxy.log
usage-stats-url: micrometer
management:
  prometheus:
    metrics:
      export:
        enabled: true

spring:
  session:
    store-type: redis
  data:
    redis:
      host: redis
      password: my_redis_password

server:
  forward-headers-strategy: native
  frame-options: sameorigin
  secure-cookies: true
  servlet:
    session:
      timeout: -1

proxy:
  store-mode: Redis
  stop-proxies-on-shutdown: false
  log-as-json: true
  admin-groups:
  - shinyproxy_admin
  container-backend: docker
  container-wait-time: 60000
  docker:
    container-network: shinyproxy_network
    internal-networking: true
    image-pull-policy: always
    privileged: false
    service-wait-time: 120000
  heartbeat-rate: 10000
  heartbeat-timeout: 60000
  logo-url: https://www.openanalytics.eu/shinyproxy/logo.png
  landing-page: /
  title: Applications
  hide-navbar: false
  port: 8080
  usage-stats-micrometer-prefix: shinyproxy
  usage-stats-url: micrometer
  authentication: openid
  openid:
    auth-url: https://my_sso.com/realms/my_realm/protocol/openid-connect/auth
    token-url: https://my_sso.com/realms/my_realm/protocol/openid-connect/token
    jwks-url: https:/my_sso.com/realms/my_realm/protocol/openid-connect/certs
    client-id: my_keycloak_client_id
    client-secret: my_keycloak_client_secret
    logout-url: https://my_sso.com/realms/my_realm/protocol/openid-connect/logout?id_token_hint=#{oidcUser.idToken.tokenValue}&returnTo=https%3A%2F%2Fmy_app.com/logout-success
    username-attribute: preferred_username
    roles-claim: groups

Keycloak

Keycloak realm settings that may be related/interesting:

Thank you in advance for your help and time!

Nour

LEDfan commented 2 weeks ago

Hi, I believe that in this specific case the issue is caused because the user has two tabs open: one with shinyproxy and any other page that is using keycloak for SSO. Because the session expires during the night, the user signs in one tab, then goes to shinyproxy and signs-in again. This will cause the already_logged_in in the keycloak logs.

I looked at the keycloak release notes and it seem there is now a specific error we can catch in ShinyProxy: https://www.keycloak.org/docs/latest/release_notes/index.html#addressed-you-are-already-logged-in-for-expired-authentication-sessions

We will look into this for the next release and try to implement a fix.

In the meanwhile, you could implement the redirect in the auth-error.html template (https://github.com/openanalytics/containerproxy/blob/master/src/main/resources/templates/auth-error.html), e.g. using:

<script>
            window.location.href = "/";
</script>
Qnouro commented 1 week ago

Hello,

Thank you for your reply. The issue occurs even if shinyproxy is the only app using keycloak and directly after rebooting the computer (so no other tab open). There may be more to dig here, though the simplest and most straight-forward approach is obviously to catch the already_logged_in error. We have implemented the suggested template override as a temporary fix. Looking forward to the next release !

Thanks again for your help, Cheers