Quansight / ragna

RAG orchestration framework ⛵️
https://ragna.chat
BSD 3-Clause "New" or "Revised" License
177 stars 21 forks source link

Login endpoint issue when launching Ragna on JupyterHub(NEbari) #275

Open dharhas opened 6 months ago

dharhas commented 6 months ago

Bug description

When I launch "ragna ui" from the command line on JupyterHub/Nebari with say:

BOKEH_ALLOW_WS_ORIGIN=nebari.quansight.dev ragna ui

Ragna is deployed with JupyterHub Server Proxy to the url:

https://nebari.quansight.dev/user/dharhas@quansight.com/proxy/31477/

This works but the the login page gets redirected to

https://nebari.quansight.dev/auth and shows a 404.

gets redirected to

https://nebari.quansight.dev/auth

manually changing the auth url to https://nebari.quansight.dev/user/dharhas@quansight.com/proxy/31477/auth

lets me login and then I can use ragna.

How to reproduce the bug?

launch a terminal on Jupyterhub/ragna and launch ragna ui

Versions and dependencies used

ragna - 0.1.3 python - 3.11.7 os - linux

Anything else?

No response

pmeier commented 6 months ago

I see that we are missing forward slashes for the auth and logout endpoints:

https://github.com/Quansight/ragna/blob/38f75f6d88e74f72c030ef50045315b81eb203aa/ragna/deploy/_ui/app.py#L109-L115

@pierrotsmnrd Do you remember if this was intentional?

I'm not saying that this is the issue here, but this the only thing that caught my eye while looking into it.

pierrotsmnrd commented 6 months ago

It was not intentional. I don't know if this has an impact or not. worth trying.

pmeier commented 6 months ago

@aktech confirmed that #276 indeed fixed the issue. However, we have for more instances of hardcoded paths for the login mechanism:

They also need be relative. This most likely has to happen in JS.

pmeier commented 4 months ago

@aktech This is solved with the PRs you have send, correct?

aktech commented 4 months ago

I have not tested it yet. I am testing is right now.

aktech commented 4 months ago

The login endpoint issue is fixed (which is what this issue is about), I am able to login via the proxy url, which takes me to the /auth.

After login the UI will look for http://127.0.0.1:31476/document (when you upload a doc), which can be fixed with creating ui and api separately, something along these lines: https://github.com/nebari-dev/jhub-apps/discussions/147 I'll give that a try to confirm if that works (I am fairly confident it should).

aktech commented 4 months ago

I just tried running two separate processes explicitly one for API and another for UI

ragna api
ragna ui --no-open-browser --no-start-api

With this ragna.toml:

# change to match your directory and same for all others below
local_root = "/home/akumar@quansight.com/.cache/ragna"
authentication = "ragna.deploy.RagnaDemoAuthentication"
document = "ragna.core.LocalDocument"
source_storages = [
    "ragna.source_storages.RagnaDemoSourceStorage",
]
assistants = [
    "ragna.assistants.RagnaDemoAssistant",
]

[api]
hostname = "127.0.0.1"
port = "31476"

# change this url to match the url of the created ragna api app url
url = "https://nebari.quansight.dev/user/akumar@quansight.com/proxy/31476"
origins = ["https://nebari.quansight.dev"]
database_url = "sqlite:////home/akumar@quansight.com/.cache/ragna/ragna.db"

[ui]
hostname = "127.0.0.1"
port = 31477
origins = [
    "http://127.0.0.1:31477",
]

Below is the error (as API is not accessible to UI without authentication and it does a 302 redirect to hub authentication)

Error Traceback ```python $ ragna ui --no-open-browser --no-start-api Launching server at http://127.0.0.1:31477 Uncaught exception GET / (127.0.0.1) HTTPServerRequest(protocol='http', host='nebari.quansight.dev', method='GET', uri='/', version='HTTP/1.1', remote_ip='127.0.0.1') Traceback (most recent call last): File "/home/conda/akumar@quansight.com/de7fbfe4-1711448219-624-ragna-only/lib/python3.11/site-packages/tornado/web.py", line 1790, in _execute result = await result ^^^^^^^^^^^^ File "/home/conda/akumar@quansight.com/de7fbfe4-1711448219-624-ragna-only/lib/python3.11/site-packages/panel/io/server.py", line 588, in get session = await self.get_session() ^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/conda/akumar@quansight.com/de7fbfe4-1711448219-624-ragna-only/lib/python3.11/site-packages/panel/io/server.py", line 477, in get_session session = await super().get_session() ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/conda/akumar@quansight.com/de7fbfe4-1711448219-624-ragna-only/lib/python3.11/site-packages/bokeh/server/views/session_handler.py", line 145, in get_session session = await self.application_context.create_session_if_needed(session_id, self.request, token) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/conda/akumar@quansight.com/de7fbfe4-1711448219-624-ragna-only/lib/python3.11/site-packages/bokeh/server/contexts.py", line 240, in create_session_if_needed self._application.initialize_document(doc) File "/home/conda/akumar@quansight.com/de7fbfe4-1711448219-624-ragna-only/lib/python3.11/site-packages/panel/io/server.py", line 413, in initialize_document super().initialize_document(doc) File "/home/conda/akumar@quansight.com/de7fbfe4-1711448219-624-ragna-only/lib/python3.11/site-packages/bokeh/application/application.py", line 190, in initialize_document h.modify_document(doc) File "/home/conda/akumar@quansight.com/de7fbfe4-1711448219-624-ragna-only/lib/python3.11/site-packages/bokeh/application/handlers/function.py", line 140, in modify_document self._func(doc) File "/home/conda/akumar@quansight.com/de7fbfe4-1711448219-624-ragna-only/lib/python3.11/site-packages/panel/io/server.py", line 152, in _eval_panel panel = panel() ^^^^^^^ File "/home/conda/akumar@quansight.com/de7fbfe4-1711448219-624-ragna-only/lib/python3.11/site-packages/ragna/deploy/_ui/app.py", line 73, in index_page api_wrapper = ApiWrapper( ^^^^^^^^^^^ File "/home/conda/akumar@quansight.com/de7fbfe4-1711448219-624-ragna-only/lib/python3.11/site-packages/ragna/deploy/_ui/api_wrapper.py", line 39, in __init__ raise e File "/home/conda/akumar@quansight.com/de7fbfe4-1711448219-624-ragna-only/lib/python3.11/site-packages/ragna/deploy/_ui/api_wrapper.py", line 32, in __init__ ).raise_for_status() ^^^^^^^^^^^^^^^^^^ File "/home/conda/akumar@quansight.com/de7fbfe4-1711448219-624-ragna-only/lib/python3.11/site-packages/httpx/_models.py", line 761, in raise_for_status raise HTTPStatusError(message, request=request, response=self) httpx.HTTPStatusError: Redirect response '302 Found' for url 'https://nebari.quansight.dev/user/akumar@quansight.com/proxy/31476/components' Redirect location: '/hub/api/oauth2/authorize?client_id=jupyterhub-user-akumar%2540quansight.com&redirect_uri=%2Fuser%2Fakumar%40quansight.com%2Foauth_callback&response_type=code&state=' ```

It didn't work as the API deployed via jupyter server proxy is supposed to be publicly accessible as the UI calls the API internally instead of on the browser as explained in here: https://github.com/nebari-dev/jhub-apps/discussions/147#discussion-6331219 (TLDR: UI hits the hub authentication before the API authentication).

I didn't see a way to expose the API publicly in the Jupyter Server Proxy @dharhas do you know if that's possible?

dharhas commented 4 months ago

@aktech we don't want the API to be publicly accessible right? it should still be behind auth but the hope would be that internally launched tools should be able to see each other.

pinging @krassowski in case he has any ideas.

aktech commented 4 months ago

@aktech we don't want the API to be publicly accessible right? it should still be behind auth but the hope would be that internally launched tools should be able to see each other.

Yes, there are two levels of authentication here:

We only want to get rid of the first one, the second one will still exist, which means the API won't be public.

krassowski commented 4 months ago

I think it is not possible to selectively disable auth in jupyter-server-proxy. One could hack it around by monkeypatching the tornado internals but I would not go that way as this is a security critical component we don't want to accidentally break.

If that was launched from jhub-apps you could presumably pass the JupyterHub auth token/cookie in the request to pass through the JupyterHub-level auth, right? Or is there a conflict because both Ragna and JupyterHub name the tokens the same way?

krassowski commented 4 months ago

In a sense, this looks like ragna should be a service with a service token (so that we are not passing the user auth token).

dharhas commented 4 months ago

Maybe the jhub-apps can launch the ragna backend as a 'service' and then the ragna frontend can be a regular app?

dharhas commented 4 months ago

A more general question is how does a user deploy rest api's that they want other apps on the platform to be able to use.