Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/content/docs/api-reference/auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ title: Auth Endpoints
description: Authentication and session management API.
---

:::note
Native username/password auth is available only when the backend runs with `ENABLE_LOCAL_USERS=true`. Otherwise register, login and refresh return `403`. See [Keycloak-only deployments](/for_developers/architecture/auth-model/#keycloak-only-deployments).
:::

## Register

Create a new local user account.
Expand All @@ -28,7 +32,7 @@ Content-Type: application/json

**Errors:**
- `400` — Missing username or password
- `403` — Registration is disabled on this instance
- `403` — User already exists, or local users are disabled on this instance (`ENABLE_LOCAL_USERS` not `true`)

---

Expand Down Expand Up @@ -63,6 +67,7 @@ Content-Type: application/json
**Errors:**
- `401` — Invalid credentials
- `400` — Missing fields
- `403` — Local users are disabled on this instance (`ENABLE_LOCAL_USERS` not `true`)

---

Expand All @@ -89,6 +94,7 @@ Cookie: refresh_token=<jwt>

**Errors:**
- `401` — Invalid or expired refresh token
- `403` — Local users are disabled on this instance (`ENABLE_LOCAL_USERS` not `true`)

---

Expand All @@ -113,6 +119,8 @@ Cookie: access_token=<jwt>

The `source` field indicates the authentication provider: `"local"` or `"keycloak"`.

When local users are disabled, this and every other protected endpoint return `403` for local users, even with a token issued before the switch.

---

## Logout
Expand Down
15 changes: 14 additions & 1 deletion src/content/docs/api-reference/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ Two authentication modes:

Protected endpoints return `401 Unauthorized` if no valid token is present.

Native auth is disabled unless the backend sets `ENABLE_LOCAL_USERS=true` (see [Keycloak-only deployments](/for_developers/architecture/auth-model/#keycloak-only-deployments)). The root endpoint reports whether it is enabled:

```http
GET /
```

```json
{
"message": "Hello World!",
"local_users_enabled": true
}
```

## Endpoint Groups

| Group | Prefix | Description |
Expand Down Expand Up @@ -79,7 +92,7 @@ These require an `update_key` (shared secret) rather than user authentication.

| Method | Path | Auth | Description |
|---|---|---|---|
| GET | `/` | No | Health check |
| GET | `/` | No | Health check, available login methods |
| PUT | `/auth/register` | No | Register user |
| POST | `/auth/login` | No | Log in |
| GET | `/auth/refresh` | Yes | Refresh token |
Expand Down
18 changes: 16 additions & 2 deletions src/content/docs/architecture/auth-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ YAPTIDE supports two authentication methods: **native Yaptide auth** (username/p

| Method | When Used | Users |
|---|---|---|
| **Yaptide Native** | Development, standalone deployments | Any registered user |
| **Yaptide Native** | Development, standalone deployments (requires `ENABLE_LOCAL_USERS=true`) | Any registered user |
| **Keycloak SSO** | Production, PLGrid-integrated deployments | PLGrid-federated users |

## Native Authentication Flow
Expand Down Expand Up @@ -129,6 +129,19 @@ The backend also:

[Local SLURM setup](/for_developers/local-setup/local-slurm/) emulates the PLGrid auth infrastructure locally. It creates a Keycloak instance and a mock certificate authority server. Keycloak config can be viewed [here](https://github.com/yaptide/yaptide/blob/68bbbf86a37b120a2708fe515e8256f1e23f28a7/slurm/keycloak/yaptide-realm.json). The mock certificate authority uses the private key `/slurm/ca_key/ca_key` to sign the certs. Entrypoint script puts the public key `/slurm/ca_key/ca_key.pub` into the Slurm cluster and configures it to trust any certificates signed by that authority.

## Keycloak-Only Deployments

Native auth is controlled by a single backend environment variable, `ENABLE_LOCAL_USERS`. Local users are **disabled by default**: unless the variable is set to a truthy value (`true`, `1`, `yes`, `on`), the instance accepts Keycloak users only. The value is parsed with [environs](https://github.com/sloria/environs); an invalid value is logged and treated as disabled.

| `ENABLE_LOCAL_USERS` | Behaviour |
|---|---|
| `true` | `PUT /auth/register` and `POST /auth/login` work, and local users can use protected endpoints. |
| unset, `false` or invalid | Register and login return `403`, and `@requires_auth` rejects tokens of local users, including refresh tokens issued before the switch. |

Keycloak login (`POST /auth/keycloak`) is not affected. Users created with `db_manage.py add-user` are local users too, so they can log in only when the flag is `true`.

The backend advertises the setting on the root endpoint (`GET /` returns `local_users_enabled`). The UI reads it during its reachability check and hides the "use password login" option when local users are disabled, so no separate frontend setting is needed.

## Demo Mode

When `REACT_APP_TARGET=demo`, authentication is bypassed entirely and only in-browser Geant4 simulations are available. See [Frontend Demo — Local](/for_developers/local-setup/local-frontend-demo/) for setup instructions.
Expand All @@ -142,7 +155,8 @@ All protected endpoints use the `@requires_auth()` decorator, which:
1. Extracts the JWT access token from the `access_token` cookie
2. Decodes and validates the token (signature, expiry)
3. Loads the `UserModel` from the database
4. Injects the `user` object into the Flask request context
4. Rejects local (`YaptideUserModel`) users with `403` unless `ENABLE_LOCAL_USERS=true`
5. Injects the `user` object into the Flask request context

```python
@requires_auth()
Expand Down
8 changes: 8 additions & 0 deletions src/content/docs/backend/docker-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ services:

## Quick Start

Local (username/password) users are disabled by default, which makes the instance Keycloak-only. For local development and testing, enable them before starting the stack, otherwise the user created below cannot log in:

```bash
cd yaptide
echo "ENABLE_LOCAL_USERS=true" >> .env
docker compose up --build -d
```

Expand All @@ -56,6 +59,8 @@ docker compose exec yaptide_flask python -m yaptide.admin.db_manage add-user \
--username admin --password admin123
```

If the stack is already running, changing `.env` takes effect only after the Flask container is recreated (`docker compose up -d yaptide_flask`); `docker compose restart` keeps the old environment.

## Compose Variants

### Standard (Production-like)
Expand Down Expand Up @@ -123,6 +128,9 @@ Set these in a `.env` file in the `yaptide/` root or pass them via Docker:
| `KEYCLOAK_BASE_URL` | Keycloak server URL |
| `KEYCLOAK_REALM` | Keycloak realm |
| `CERT_AUTH_URL` | PLGrid cert-auth service URL |
| `ENABLE_LOCAL_USERS` | Allow local (username/password) users. Defaults to `false` (Keycloak-only); set to `true` to log in with users created by `db_manage.py add-user` |

See [Keycloak-only deployments](/for_developers/architecture/auth-model/#keycloak-only-deployments) for details.

### Simulator Storage (S3)

Expand Down
1 change: 1 addition & 0 deletions src/content/docs/backend/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ All large data (input files, simulation results, logs) is **gzip-compressed** be
| `KEYCLOAK_BASE_URL` | Keycloak server URL |
| `KEYCLOAK_REALM` | Keycloak realm |
| `CERT_AUTH_URL` | PLGrid SSH cert service URL |
| `ENABLE_LOCAL_USERS` | Allow native username/password users (register, login). Default: disabled, so the instance is Keycloak-only |
| `MAX_CORES` | CPU limit for simulation worker |
| `LOG_LEVEL_ROOT` | Logging verbosity |

Expand Down
2 changes: 1 addition & 1 deletion src/content/docs/backend/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def test_health_check(client):

### Authenticated Tests

Most endpoints require authentication. Use the login fixture:
Most endpoints require authentication. `pytest.ini` sets `ENABLE_LOCAL_USERS=true` so tests can register and log in local users:

```python
def test_submit_simulation(client):
Expand Down
10 changes: 10 additions & 0 deletions src/content/docs/docker-setup/docker-celery.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ Navigate to the `yaptide/` directory:
cd yaptide
```

Local (username/password) users are disabled by default. To log in with the user created below, create a `.env` file in the `yaptide/` directory first:

```bash title="yaptide/.env"
ENABLE_LOCAL_USERS=true
```

Two startup options are available:

**Standard mode** — builds and starts all containers:
Expand Down Expand Up @@ -120,6 +126,10 @@ docker compose up

Open **http://localhost** and log in using credentials you created (username: `admin`, password: `password`). The setup is complete now.

:::tip[Login fails with 403?]
If logging in shows *Local user login is disabled on this instance*, the backend was started without `ENABLE_LOCAL_USERS=true`. Local users are disabled by default, so add it to `yaptide/.env` as described above and re-run the start script, which recreates the containers with the new setting.
:::

:::caution
With a Chromium-based browser, use `https://localhost:8443` as the backend URL instead of `http://localhost:5000` to avoid cookie issues with browser security policies.
```bash title="ui/.env"
Expand Down
2 changes: 2 additions & 0 deletions src/content/docs/frontend/auth-flows.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ The frontend supports two authentication modes and a demo mode that bypasses aut
| **Keycloak SSO** (PLGrid) | `REACT_APP_ALT_AUTH=plg` | Yes + Keycloak |
| **Demo** (no auth) | `REACT_APP_TARGET=demo` | No |

In Keycloak SSO mode the login panel also offers a "use password login" link. It is hidden when the backend reports `local_users_enabled: false` on `GET /` (read by the reachability check in `AuthService.tsx` and exposed as `localUsersEnabled` on the auth context). Backends that do not report the flag are treated as allowing local users.

## Standard Authentication

### Login Flow
Expand Down
10 changes: 8 additions & 2 deletions src/content/docs/local-setup/local-celery.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,14 @@ Open a third backend terminal and go to the `yaptide/` directory. Run:
<TabItem label="Linux">

```bash
FLASK_SQLALCHEMY_ECHO=True FLASK_USE_CORS=True FLASK_SQLALCHEMY_DATABASE_URI="sqlite:///db.sqlite" CELERY_BROKER_URL=redis://127.0.0.1:6379/0 CELERY_RESULT_BACKEND=redis://127.0.0.1:6379/0 poetry run flask --debug --app yaptide.application run
FLASK_SQLALCHEMY_ECHO=True FLASK_USE_CORS=True ENABLE_LOCAL_USERS=true FLASK_SQLALCHEMY_DATABASE_URI="sqlite:///db.sqlite" CELERY_BROKER_URL=redis://127.0.0.1:6379/0 CELERY_RESULT_BACKEND=redis://127.0.0.1:6379/0 poetry run flask --debug --app yaptide.application run
```

</TabItem>
<TabItem label="Windows (PowerShell)">

```powershell
$env:FLASK_SQLALCHEMY_ECHO="True"; $env:FLASK_USE_CORS="True"; $env:FLASK_SQLALCHEMY_DATABASE_URI="sqlite:///db.sqlite"; $env:CELERY_BROKER_URL="redis://127.0.0.1:6379/0"; $env:CELERY_RESULT_BACKEND="redis://127.0.0.1:6379/0"; poetry run flask --debug --app yaptide.application run
$env:FLASK_SQLALCHEMY_ECHO="True"; $env:FLASK_USE_CORS="True"; $env:ENABLE_LOCAL_USERS="true"; $env:FLASK_SQLALCHEMY_DATABASE_URI="sqlite:///db.sqlite"; $env:CELERY_BROKER_URL="redis://127.0.0.1:6379/0"; $env:CELERY_RESULT_BACKEND="redis://127.0.0.1:6379/0"; poetry run flask --debug --app yaptide.application run
```

</TabItem>
Expand All @@ -197,6 +197,8 @@ This creates `db.sqlite` inside `./instance/` (default [Flask instance folder](h

`FLASK_SQLALCHEMY_ECHO=True` enables SQL query logging for debugging database interactions.

`ENABLE_LOCAL_USERS=true` allows logging in with a username and password. Local users are disabled by default, so without it the login in the next steps fails with `403`.

### 7. Create a user

Before logging in from the frontend, you need to create a user in the database. Open the 4th terminal and go to the `yaptide/` directory. Run:
Expand Down Expand Up @@ -266,6 +268,10 @@ npm run start

Open **http://localhost:3000**. Log in with the credentials you created (username: `admin`, password: `password`). The setup is complete now. The page reloads on edits.

:::tip[Login fails with 403?]
If logging in shows *Local user login is disabled on this instance*, the backend was started without `ENABLE_LOCAL_USERS=true`. Local users are disabled by default, so add `ENABLE_LOCAL_USERS=true` to the Flask command in [step 6](#6-start-the-flask-api) and restart it.
:::

:::caution
Access both frontend and backend using the **same domain** — either both `localhost` or both `127.0.0.1`. Mixing them breaks cookie-based authentication (`SameSite=Lax` policy).
:::
Expand Down
Loading