From ce773ec2f18c6c0a7960c2366f855503866664c7 Mon Sep 17 00:00:00 2001 From: mark <18689435+markendr@users.noreply.github.com> Date: Sun, 19 Apr 2026 12:21:33 +1000 Subject: [PATCH 1/2] add user authorization using jwt groups claim --- VSCODE.md | 101 +++++++++++++++++++++++++++++++++++ backend/app/config.py | 1 + backend/app/keycloak_auth.py | 11 +++- frontend/src/types/action.ts | 7 +++ pyproject.toml | 3 ++ 5 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 VSCODE.md diff --git a/VSCODE.md b/VSCODE.md new file mode 100644 index 000000000..eb07c8dfb --- /dev/null +++ b/VSCODE.md @@ -0,0 +1,101 @@ +## VS Code development + +To run and debug the Clowder frontend and backend apps in VS Code IDE from the +WSL Ubuntu 24.04 LTS distribution + +1. Start VS Code, install the WSL (Windows Subsystem for Linux) extension, + then exit + +2. Open Ubuntu 24.04 WSL terminal and clone the clowder2 repo + + ``` + git clone https://github.com/clowder-framework/clowder2.git + cd clowder2 + ``` + +3. Install NPM needed for building frontend + + ``` + sudo apt install npm + ``` + +4. Install frontend dependencies + + ``` + cd frontend + npm install + cd .. + ``` + +5. Install Python version needed for backend, eg. + + ``` + wget http://www.python.org/ftp/python/3.10.19/Python-3.10.19.tgz + tar xzf Python-3.10.19.tgz + mkdir $HOME/.local/python + cd Python-3.10.19/ + ./configure --prefix=$HOME/.local/python + make + make install + ``` + +6. Create a Python virtualenv and install backend dependencies + + ``` + cd clowder2 + $HOME/.local/python/bin/python3 -m venv venv + . venv/bin/activate + pip install . + deactivate + ``` + +7. Start local docker dependencies + + ``` + cd clowder2 + docker compose -f docker-compose.dev.yml -p clowder2-dev up -d + # to stop use + docker compose -p clowder2-dev down + ``` + +8. Add TCP proxy ports for forwarding Windows browser connections for the + frontend, backend and Keycloak to WSL + + Get WSL IP address for `eth0` in WSL terminal + + ``` + ip -br a show dev eth0 + ``` + + Add TCP proxy ports in PowerShell admin terminal + + ``` + netsh interface portproxy show v4tov4 + netsh interface portproxy add v4tov4 listenport=3000 listenaddress=0.0.0.0 connectport=3000 connectaddress= + netsh interface portproxy add v4tov4 listenport=8000 listenaddress=0.0.0.0 connectport=8000 connectaddress= + netsh interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=8080 connectaddress= + ``` + +9. Start VS Code from your WSL terminal + + ``` + cd clowder2 + code . + ``` + +10. Set the VS Code Python interpreter + + 1. Open Command Palette (Ctrl+Shift+P) + 2. Click **Python: Select Interpreter** from list, set it to `./venv/bin/python` + +11. Start Clowder backend in VS Code Run and Debug view + + 1. Select **Python Debugger: FastAPI** + 2. Click **Start Debugging** + +12. Start Clowder frontend in VS Code Run and Debug view + + 1. Select **Launch via npm** + 2. Click **Start Debugging** + +13. Open [Clowder](http://localhost:3000/) in your Windows Edge or Chrome browser diff --git a/backend/app/config.py b/backend/app/config.py index 8f1d043c6..b00996804 100644 --- a/backend/app/config.py +++ b/backend/app/config.py @@ -59,6 +59,7 @@ class Settings(BaseSettings): ) auth_server_url = f"{auth_base}/keycloak/" auth_client_secret = "" + auth_role = "clowder2" # keycloak local config keycloak_username = "admin" diff --git a/backend/app/keycloak_auth.py b/backend/app/keycloak_auth.py index 062424890..aa6c762a0 100644 --- a/backend/app/keycloak_auth.py +++ b/backend/app/keycloak_auth.py @@ -62,7 +62,7 @@ async def get_token( if token: try: # See https://github.com/marcospereirampj/python-keycloak/issues/89 - return keycloak_openid.decode_token( + payload = keycloak_openid.decode_token( token, key=await get_idp_public_key(), options={"verify_aud": False}, @@ -85,6 +85,15 @@ async def get_token( detail=str(e), headers={"WWW-Authenticate": "Bearer"}, ) + if settings.auth_role: + groups: list = payload.get("groups", {}) + if settings.auth_role not in groups: + raise HTTPException( + status_code=403, + detail="Not authorized.", + headers={"WWW-Authenticate": "Bearer"}, + ) + return payload if api_key: serializer = URLSafeSerializer(settings.local_auth_secret, salt="api_key") diff --git a/frontend/src/types/action.ts b/frontend/src/types/action.ts index 54ab4f10b..707e9bde1 100644 --- a/frontend/src/types/action.ts +++ b/frontend/src/types/action.ts @@ -293,6 +293,12 @@ interface NOT_FOUND_INLINE { reason: string; } +interface NOT_AUTHORIZED { + stack: string; + type: "NOT_AUTHORIZED"; + reason: string; +} + interface RESET_FAILED { type: "RESET_FAILED"; reason: string; @@ -777,6 +783,7 @@ export type DataAction = | FAILED_INLINE | NOT_FOUND | NOT_FOUND_INLINE + | NOT_AUTHORIZED | RESET_FAILED | RESET_FAILED_INLINE | RESET_LOGOUT diff --git a/pyproject.toml b/pyproject.toml index 31b1abbbd..402c20acf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,6 +7,7 @@ description = """Clowder is a cloud native data management framework to support readme = "README.md" requires-python = ">=3.10" dependencies = [ + "charset_normalizer==3.4.0", "fastapi==0.95.1", "pydantic==1.10.13", "uvicorn==0.21.1", @@ -45,3 +46,5 @@ dev = [ docs = [ "mkdocs-material" ] +[tool.setuptools] +py-modules = [] From 8eea02dca3aff009367ff033eafba98b26b510b9 Mon Sep 17 00:00:00 2001 From: mark <18689435+markendr@users.noreply.github.com> Date: Sun, 19 Apr 2026 13:26:30 +1000 Subject: [PATCH 2/2] add vs code launch.json --- .vscode/launch.json | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..e1ec5812c --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,28 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python Debugger: FastAPI", + "type": "debugpy", + "request": "launch", + "cwd": "${workspaceFolder}/backend", + "module": "uvicorn", + "args": [ "app.main:app", "--host", "0.0.0.0", "--reload" ] + }, + { + "name": "Launch via npm", + "type": "node", + "request": "launch", + "cwd": "${workspaceFolder}/frontend", + "env": { + "CLOWDER_REMOTE_HOSTNAME": "http://localhost:8000" + }, + "runtimeExecutable": "npm", + "runtimeArgs": ["run", "start"], + "outFiles": ["${workspaceFolder}/frontend/src"] + } + ] +}