Skip to content
Merged
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
2 changes: 1 addition & 1 deletion bfabric/docs/api_reference/bfabric_client/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Complete API reference for the `Bfabric` client class, automatically generated f

## Quick Links

- **[Creating a Client](../../user_guides/creating_a_client/index.md)** - Step-by-step guides for different use cases
- **[Connecting](../../user_guides/connecting/index.md)** - Step-by-step guides for different use cases
- **[Configuration](../../getting_started/configuration.md)** - Config file setup and options
- **[Quick Start](../../getting_started/quick_start.md)** - 5-minute tutorial

Expand Down
2 changes: 1 addition & 1 deletion bfabric/docs/api_reference/token_data/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,4 @@ print(f"Loaded entity: {entity}")

## See Also

- [Server/Webapp Usage](../../user_guides/creating_a_client/server_webapp_usage.md) - Server authentication guide
- [Server/Webapp Usage](../../user_guides/connecting/server_webapp_usage.md) - Server authentication guide
2 changes: 1 addition & 1 deletion bfabric/docs/design/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ oauth_usage_and_troubleshooting
| --- | --- |
| **[`bfabric.operations` Module](operations_module.md)** | Conventions and worked examples for named write capabilities (`create_workunit`, `create_dataset`, …), including the failure-cleanup pattern and the audit-vs-authorization split. |
| **[OAuth Integration](oauth_integration.md)** | The `bfabric.oauth` module and OAuth 2.0 flows (PKCE, device code, client credentials, URL token, PAT), the `Bfabric.connect_*` factory methods, `bfabric-cli auth` commands, and the config/scope model. |
| **[OAuth Usage & Troubleshooting](oauth_usage_and_troubleshooting.md)** | Task-oriented (experimental): obtaining a working token, access_token vs id_token, the `containers` claim for file/download access, `.well-known` discovery, and PKCE gotchas (loopback redirect, public-only clients, remote notebooks). |
| **[OAuth Usage & Troubleshooting](oauth_usage_and_troubleshooting.md)** | Task-oriented: obtaining a working token, access_token vs id_token, the `containers` claim for file/download access, `.well-known` discovery, and PKCE gotchas (loopback redirect, public-only clients, remote notebooks). |
3 changes: 1 addition & 2 deletions bfabric/docs/design/oauth_integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ The core `oauth` API requires explicit `client_id` and `scope` arguments on all
| `Bfabric.connect_oauth(client_id, client_secret, base_url)` | client_credentials | Service accounts / background jobs. |
| `Bfabric.connect_pkce(base_url, client_id)` | authorization_code + PKCE | Interactive browser login (programmatic). |
| `Bfabric.connect_device_code(base_url, client_id)` | device_code | Headless interactive login (programmatic). |
| `Bfabric.from_url_token(base_url, jwt, refresh_token)` | URL token | Webapps launched from B-Fabric. Returns `(Bfabric, UrlTokenContext)`. |
| `WebappClient.create(base_url, jwt, ..., client_id, client_secret)` | URL token + client_credentials | Dual-identity webapp client. |
| `WebappClient.create(base_url, launch_token, ..., client_id, client_secret)` | URL token + client_credentials | Dual-identity webapp client for apps launched from B-Fabric. |

---

Expand Down
5 changes: 0 additions & 5 deletions bfabric/docs/design/oauth_usage_and_troubleshooting.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
# OAuth Usage & Troubleshooting

> **⚠️ EXPERIMENTAL / NOT OFFICIALLY SHIPPED.** The `bfabric.oauth` module and the
> `connect_pkce` / `connect_device_code` / `connect_oauth` factory methods are under active
> development (the asgi-auth OAuth migration is still in flight). APIs, defaults, and server-side
> scope enforcement may change. Do not treat this as stable public API yet.

A task-oriented companion to [OAuth Integration](oauth_integration.md): how to obtain a working
token from a `Bfabric` client via OAuth, and the non-obvious failure modes observed on
`fgcz-bfabric-demo`. For the architecture and module layout, see the integration doc.
Expand Down
56 changes: 46 additions & 10 deletions bfabric/docs/getting_started/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ bfabricPy can be configured through config files, environment variables, or code

## Configuration File (Recommended)

Create a YAML file at `~/.bfabricpy.yml`:
The config file lives at `~/.bfabricpy.yml`. The simplest way to create it is to log in:

```bash
bfabric-cli login
```

That writes an environment for the instance you picked:

```yaml
# ~/.bfabricpy.yml
Expand All @@ -13,19 +19,49 @@ GENERAL:
default_config: PRODUCTION # Default environment to use

PRODUCTION:
login: yourBfabricLogin
password: yourBfabricWebServicePassword # Get from B-Fabric profile
base_url: https://fgcz-bfabric.uzh.ch/bfabric/
auth_method: oauth
client_id: CLI
scope: api:read

TEST:
login: yourBfabricLogin
password: yourBfabricWebServicePassword
base_url: https://fgcz-bfabric-test.uzh.ch/bfabric/
auth_method: oauth
client_id: CLI
scope: api:write
```

### Web Service Password
The token itself is not stored here — it lives in a separate cache under `~/.bfabric/tokens/`, and
`Bfabric.connect()` refreshes it as needed. See [CLI Authentication](../user_guides/bfabric-cli/authentication.md) for
scopes and for managing several environments.

### Personal Access Tokens

`bfabric-cli auth pat` stores a token inline instead, for non-interactive logins:

```yaml
PRODUCTION:
base_url: https://fgcz-bfabric.uzh.ch/bfabric/
auth_method: pat
pat: yourPersonalAccessToken
```

### Web Service Password (Legacy)

```{note}
Web service passwords are being phased out in favour of `bfabric-cli login`. Prefer OAuth for new setups.
```

An environment can also hold a login and web service password directly:

```yaml
PRODUCTION:
login: yourBfabricLogin
password: yourBfabricWebServicePassword # Get from B-Fabric profile
base_url: https://fgcz-bfabric.uzh.ch/bfabric/
```

The password in your config file is **NOT** your login password. Find your web service password:
The password here is **NOT** your login password. Find your web service password:

1. Log into B-Fabric web interface
2. Go to your profile page
Expand Down Expand Up @@ -119,7 +155,7 @@ auth = BfabricAuth(

For web applications that receive B-Fabric tokens, see:

- [Server/Webapp Usage](../user_guides/creating_a_client/server_webapp_usage.md)
- [Server/Webapp Usage](../user_guides/connecting/server_webapp_usage.md)

## Best Practices

Expand All @@ -132,6 +168,6 @@ For web applications that receive B-Fabric tokens, see:
## See Also

- [Installation Guide](installation.md) - Installation options
- [Creating a Client Guide](../user_guides/creating_a_client/index.md) - How to use configuration
- [Server/Webapp Configuration](../user_guides/creating_a_client/server_webapp_usage.md) - Token-based auth
- [Connecting Guide](../user_guides/connecting/index.md) - How to use configuration
- [Server/Webapp Configuration](../user_guides/connecting/server_webapp_usage.md) - Token-based auth
- [Troubleshooting](troubleshooting.md) - Common issues and solutions
4 changes: 2 additions & 2 deletions bfabric/docs/getting_started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ ______________________________________________________________________

After installing the packages:

1. **Configure your credentials**: [Configuration Guide](configuration.md)
1. **Log in**: run `bfabric-cli login`, or see the [Configuration Guide](configuration.md) for the other options
2. **Try it out**:
- For Python usage: [Quick Start Tutorial](quick_start)
- For CLI usage: [bfabric-cli User Guide](../user_guides/bfabric-cli/index)
Expand All @@ -159,4 +159,4 @@ ______________________________________________________________________
- [Configuration Guide](configuration) - Setting up config files and environment variables
- [Quick Start Tutorial](quick_start) - Your first bfabricPy script
- [bfabric-cli User Guide](../user_guides/bfabric-cli/index) - Command-line interface documentation
- [Creating a Client](../user_guides/creating_a_client/index) - Using bfabric in Python code
- [Connecting](../user_guides/connecting/index) - Using bfabric in Python code
8 changes: 4 additions & 4 deletions bfabric/docs/getting_started/quick_start.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This 5-minute tutorial will get you started with bfabricPy by writing your first
Before starting, make sure you have:

1. **Installed bfabricPy**: Follow [Installation Guide](installation.md)
2. **Configured credentials**: Follow [Configuration Guide](configuration.md)
2. **Logged in**: run `bfabric-cli login`, or see the [Configuration Guide](configuration.md) for the other options

______________________________________________________________________

Expand Down Expand Up @@ -66,7 +66,7 @@ Import the main Bfabric class.
client = Bfabric.connect()
```

Create a client using your configuration from `~/.bfabricpy.yml`.
Connect using your configuration from `~/.bfabricpy.yml`.

```python
results = client.read(endpoint="workunit", obj={}, max_results=5)
Expand Down Expand Up @@ -105,7 +105,7 @@ Now that you've seen the basics, explore further:

| Want to... | Read this guide |
| ------------------------------------- | ---------------------------------------------------------------------- |
| Understand client authentication | [Creating a Client](../user_guides/creating_a_client/index.md) |
| Understand client authentication | [Connecting](../user_guides/connecting/index.md) |
| Query and retrieve data efficiently | [Reading Data](../user_guides/reading_data/index.md) |
| Create, update, delete entities | [Writing Data](../user_guides/writing_data/index) |
| Use typed entities with relationships | [Working with Entities](../user_guides/working_with_entities/index) |
Expand All @@ -116,5 +116,5 @@ Now that you've seen the basics, explore further:
- [Installation Guide](installation) - Installation options
- [Configuration Guide](configuration) - Config file structure and options
- [API Inspection Guide](../user_guides/bfabric-cli/api_inspection) - Discovering API endpoints and parameters
- [Creating a Client](../user_guides/creating_a_client/index) - Authentication methods
- [Connecting](../user_guides/connecting/index) - Authentication methods
- [Troubleshooting](troubleshooting) - Common issues and solutions
34 changes: 34 additions & 0 deletions bfabric/docs/user_guides/connecting/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Connecting

bfabricPy supports different authentication methods depending on your use case.

```{toctree}
:maxdepth: 1
interactive_scripted_usage
server_webapp_usage
```

## Choose Your Approach

| Use Case | Method | Documentation |
| ------------------------------------------ | ---------------------------------------------------------- | ----------------------------------------------------------- |
| Scripts, local tools, interactive sessions | `bfabric-cli login` once, then `Bfabric.connect()` | [Interactive/Scripted Usage](interactive_scripted_usage.md) |
| Logging in from Python, without the CLI | `Bfabric.connect_pkce()` / `Bfabric.connect_device_code()` | [Interactive/Scripted Usage](interactive_scripted_usage.md) |
| Non-interactive token | `Bfabric.connect_pat()` | [Interactive/Scripted Usage](interactive_scripted_usage.md) |
| Background jobs, service accounts | `Bfabric.connect_oauth()` | [Server/Webapp Usage](server_webapp_usage.md) |
| Webapps launched from B-Fabric | `Bfabric.connect_token()` / `WebappClient.create()` | [Server/Webapp Usage](server_webapp_usage.md) |

## Next Steps

After connecting, learn how to work with B-Fabric:

- **[Reading Data](../reading_data/index.md)** - Query and retrieve data
- **[Writing Data](../writing_data/index.md)** - Create, update, and delete entities
- **[Working with Entities](../working_with_entities/index.md)** - Use typed entities and relationships

## See Also

- [CLI Authentication](../bfabric-cli/authentication.md) - `bfabric-cli auth` commands, scopes, multiple instances
- [Configuration Guide](../../getting_started/configuration.md) - Setting up config files
- [API Reference: Bfabric Client](../../api_reference/bfabric_client/index.md) - Complete client documentation
- [Error Handling](../error_handling.md) - Authentication errors
174 changes: 174 additions & 0 deletions bfabric/docs/user_guides/connecting/interactive_scripted_usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# Interactive and Scripted Usage

This guide covers how to connect a `Bfabric` client in interactive sessions and scripts, where you control the
configuration directly through config files or environment variables.

## Log In Once, Connect From Code

Log in with the CLI:

```bash
bfabric-cli login
```

On a first run this asks which instance you want and which permissions to request, and stores both in
`~/.bfabricpy.yml`. Afterwards your scripts just connect:

```python
from bfabric import Bfabric

client = Bfabric.connect()
```

`connect()` sees `auth_method: oauth` in the selected environment, picks up the cached token and refreshes it when it
nears expiry — nothing OAuth-specific appears in your code. When the login itself expires, run `bfabric-cli login` again
with no arguments; everything it needs was recorded the first time.

See [CLI Authentication](../bfabric-cli/authentication.md) for scopes, working with several instances, and logging out.

## Choosing an Environment

`~/.bfabricpy.yml` can hold several environments (a production and a test instance, or two logins on the same instance
with different permissions). By default `connect()` uses `BFABRICPY_CONFIG_ENV` if it is set, otherwise the config
file's default environment. You can also name one explicitly:

```python
# Use the PRODUCTION environment
client = Bfabric.connect(config_file_env="PRODUCTION")

# Use the TEST environment
client = Bfabric.connect(config_file_env="TEST")
```

The `config_file_env` parameter takes precedence over the `BFABRICPY_CONFIG_ENV` environment variable. See the
[Configuration Guide](../../getting_started/configuration.md#priority-order) for the full priority order.

If your config file is in a non-standard location:

```python
from pathlib import Path

custom_config_path = Path("/path/to/custom/config.yml")
client = Bfabric.connect(
config_file_path=custom_config_path, config_file_env="PRODUCTION"
)
```

## Logging In From Python

If you would rather not depend on the CLI having been run, you can perform the login from Python. Both flows take an
explicit `client_id` and `scope`, and both accept a `token_cache_path` that the resulting client refreshes against.

On a local machine, `connect_pkce()` opens your browser and waits for the redirect:

```python
from bfabric import Bfabric

client = Bfabric.connect_pkce(
"https://fgcz-bfabric.uzh.ch/bfabric",
client_id="CLI",
scope="api:read",
)
```

On a remote host — SSH, a container, a hosted notebook — use `connect_device_code()` instead. It prints a code to enter
in a browser anywhere and polls for the result:

```python
client = Bfabric.connect_device_code(
"https://fgcz-bfabric.uzh.ch/bfabric",
client_id="CLI",
scope="api:read",
)
```

Each call runs the login again — neither skips it by reading the cache — so keep them out of code that reruns often.

```{note}
The browser flow finishes by redirecting to a port on the machine running Python. If the browser is on a different
machine, nothing is listening there and the login times out — which is why remote hosts need the device code flow. See
[OAuth Usage & Troubleshooting](../../design/oauth_usage_and_troubleshooting.md) for the details.
```

## Personal Access Tokens

For a non-interactive login without any OAuth flow, use a Personal Access Token issued by B-Fabric:

```python
client = Bfabric.connect_pat("https://fgcz-bfabric.uzh.ch/bfabric", pat="your_token")
```

PATs are not refreshed automatically; when one expires you need a new one. `bfabric-cli auth pat` stores a PAT in your
config file, so `Bfabric.connect()` picks it up like any other environment.

## Web Service Password

```{note}
Web service passwords are being phased out in favour of the OAuth login above. Prefer `bfabric-cli login` for new setups.
```

An environment can also hold a B-Fabric login and web service password directly:

```yaml
PRODUCTION:
login: yourBfabricLogin
password: yourBfabricWebServicePassword
base_url: https://fgcz-bfabric.uzh.ch/bfabric/
```

`Bfabric.connect()` uses these the same way — the auth method is a property of the environment, not of the call.

## Temporarily Changing Authentication

The `with_auth()` context manager allows you to temporarily set authentication for a `Bfabric` client. This is useful when
authenticating multiple users to avoid accidental use of the wrong credentials:

```python
from bfabric import Bfabric
from bfabric.config import BfabricAuth

client = Bfabric.connect()

# Temporarily use different credentials
with client.with_auth(BfabricAuth(login="other_user", password="other_pass")):
# All operations in this block use different authentication
samples = client.read(endpoint="sample", obj={"name": "Test"})

# Authentication is restored after the block
samples = client.read(endpoint="sample", obj={"name": "Test"})

print(f"Current user: {client.auth.login}") # Shows original user
```

On an OAuth client the automatic token refresh is suspended for the duration of the block, so the credentials you pass
are the ones that get used.

## Without Authentication

For certain use cases (e.g. tests, read-only operations on public endpoints), you may want to create a client without
authentication:

```python
# Disable authentication - useful for tests
client = Bfabric.connect(config_file_env=None, include_auth=False)
```

```{warning}
Without authentication, you won't be able to perform operations that require credentials, such as creating or updating
entities.
```

## Verification

Always verify you're using the correct environment:

```python
from bfabric import Bfabric

client = Bfabric.connect()
print(f"Connected to: {client.config.base_url}")
print(f"User: {client.auth.login}")
```

For an OAuth environment `client.auth.login` is the placeholder `__oauth__` rather than your username — use
`bfabric-cli auth status` to see who you are logged in as and when the token expires.
Loading