Skip to content

Commit 1c74a4c

Browse files
authored
docs: update QUICKSTART.md for simple plugin architecture (#24)
1 parent 0f8bd7a commit 1c74a4c

File tree

2 files changed

+133
-133
lines changed

2 files changed

+133
-133
lines changed

README.md

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,9 @@ response = descope_client.magiclink.sign_in_or_up(
6565
login_id="user@example.com"
6666
)
6767

68-
# Extract tokens
68+
# Extract session token
6969
session_token = response["sessionToken"]["jwt"]
70-
refresh_token = response["refreshToken"]["jwt"]
71-
7270
print(f"export DESCOPE_SESSION_TOKEN='{session_token}'")
73-
print(f"export DESCOPE_REFRESH_TOKEN='{refresh_token}'")
7471
```
7572

7673
### 3. Set Environment Variables
@@ -79,7 +76,6 @@ print(f"export DESCOPE_REFRESH_TOKEN='{refresh_token}'")
7976
# Required
8077
export DESCOPE_PROJECT_ID="P2XXXXX"
8178
export DESCOPE_SESSION_TOKEN="<your-session-token>"
82-
export DESCOPE_REFRESH_TOKEN="<your-refresh-token>"
8379

8480
# Optional (with defaults)
8581
export DESCOPE_ADMIN_ROLES="admin,mlflow-admin"
@@ -197,15 +193,14 @@ descope = "mlflow_descope_auth.context_provider:DescopeContextProvider"
197193

198194
## Configuration Reference
199195

200-
| Variable | Required | Default | Description |
201-
| ------------------------- | -------- | -------------------- | ----------------------------------------------- |
202-
| `DESCOPE_PROJECT_ID` | ✅ Yes | - | Your Descope Project ID |
203-
| `DESCOPE_SESSION_TOKEN` | ✅ Yes | - | Current session JWT token |
204-
| `DESCOPE_REFRESH_TOKEN` | ❌ No | - | Refresh token for automatic renewal |
205-
| `DESCOPE_ADMIN_ROLES` | ❌ No | `admin,mlflow-admin` | Comma-separated list of admin roles |
206-
| `DESCOPE_DEFAULT_PERMISSION` | ❌ No | `READ` | Default permission level (READ/EDIT/MANAGE) |
207-
| `DESCOPE_USERNAME_CLAIM` | ❌ No | `sub` | JWT claim to use as username (`sub` or `email`) |
208-
| `MLFLOW_TRACKING_AUTH` | ✅ Yes | - | Set to `descope` to enable plugin |
196+
| Variable | Required | Default | Description |
197+
| ---------------------------- | -------- | -------------------- | ----------------------------------------------- |
198+
| `DESCOPE_PROJECT_ID` | ✅ Yes | - | Your Descope Project ID |
199+
| `DESCOPE_SESSION_TOKEN` | ✅ Yes | - | Current session JWT token |
200+
| `DESCOPE_ADMIN_ROLES` | ❌ No | `admin,mlflow-admin` | Comma-separated list of admin roles |
201+
| `DESCOPE_DEFAULT_PERMISSION` | ❌ No | `READ` | Default permission level (READ/EDIT/MANAGE) |
202+
| `DESCOPE_USERNAME_CLAIM` | ❌ No | `sub` | JWT claim to use as username (`sub` or `email`) |
203+
| `MLFLOW_TRACKING_AUTH` | ✅ Yes | - | Set to `descope` to enable plugin |
209204

210205
## Architecture
211206

@@ -257,10 +252,7 @@ python -c "
257252
from mlflow_descope_auth import get_descope_client
258253
import os
259254
client = get_descope_client()
260-
result = client.validate_session(
261-
os.environ['DESCOPE_SESSION_TOKEN'],
262-
os.environ.get('DESCOPE_REFRESH_TOKEN')
263-
)
255+
result = client.validate_session(os.environ['DESCOPE_SESSION_TOKEN'])
264256
print('✓ Token valid')
265257
"
266258
```

docs/QUICKSTART.md

Lines changed: 123 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Get MLflow running with Descope authentication in 5 minutes!
44

55
## Prerequisites
66

7-
- Python 3.8 or higher installed
7+
- Python 3.9 or higher installed
88
- pip package manager
99
- A Descope account (free at [descope.com](https://www.descope.com/))
1010

@@ -15,17 +15,32 @@ Get MLflow running with Descope authentication in 5 minutes!
1515
3. Give it a name (e.g., "MLflow Auth")
1616
4. Copy your **Project ID** (starts with `P2`)
1717

18-
## Step 2: Configure Authentication Flow
18+
## Step 2: Get Authentication Tokens
1919

20-
1. In Descope Console, go to **Authentication → Flows**
21-
2. You'll see a default `sign-up-or-in` flow - click to edit
22-
3. Add your desired authentication methods:
23-
- **OAuth**: Google, GitHub, Microsoft, etc.
24-
- **Magic Link**: Passwordless email authentication
25-
- **OTP**: SMS or email one-time password
26-
- **Password**: Traditional username/password
20+
Authenticate with Descope to obtain session tokens. You can use the Descope Python SDK:
2721

28-
4. Click **Publish** to save your flow
22+
```python
23+
from descope import DescopeClient
24+
25+
descope_client = DescopeClient(project_id="P2XXXXX")
26+
27+
# Authenticate user (example with magic link)
28+
response = descope_client.magiclink.sign_in_or_up(
29+
method="email",
30+
login_id="user@example.com"
31+
)
32+
33+
# Extract session token
34+
session_token = response["sessionToken"]["jwt"]
35+
print(f"export DESCOPE_SESSION_TOKEN='{session_token}'")
36+
```
37+
38+
Or use any other Descope authentication method (OAuth, SAML, etc.) via:
39+
- [Descope Web SDK](https://docs.descope.com/build/guides/client_sdks/web/)
40+
- [Descope Python SDK](https://docs.descope.com/build/guides/client_sdks/python/)
41+
- Descope API directly
42+
43+
> **Note**: Token refresh is handled automatically by the server, not via environment variables.
2944
3045
## Step 3: Install MLflow Descope Auth
3146

@@ -35,177 +50,170 @@ pip install mlflow-descope-auth
3550

3651
## Step 4: Configure Environment
3752

38-
Create a `.env` file in your project directory:
53+
Set the required environment variables:
3954

4055
```bash
41-
# Required: Your Descope Project ID
42-
DESCOPE_PROJECT_ID=P2XXXXX
56+
# Required
57+
export DESCOPE_PROJECT_ID="P2XXXXX"
58+
export DESCOPE_SESSION_TOKEN="<your-session-token>"
4359

44-
# Optional: Flow ID (default is "sign-up-or-in")
45-
DESCOPE_FLOW_ID=sign-up-or-in
60+
# Enable the plugin
61+
export MLFLOW_TRACKING_AUTH=descope
4662

47-
# Optional: Where to redirect after login (default is "/")
48-
DESCOPE_REDIRECT_URL=/
63+
# Optional (with defaults)
64+
export DESCOPE_ADMIN_ROLES="admin,mlflow-admin"
65+
export DESCOPE_DEFAULT_PERMISSION="READ"
66+
export DESCOPE_USERNAME_CLAIM="sub" # or "email"
4967
```
5068

51-
## Step 5: Run MLflow
69+
## Step 5: Use MLflow
5270

53-
```bash
54-
mlflow server --app-name descope-auth --host 0.0.0.0 --port 5000
55-
```
71+
Once configured, the plugin works automatically with any MLflow client:
72+
73+
```python
74+
import mlflow
5675

57-
## Step 6: Test Authentication
76+
# Set tracking URI to your MLflow server
77+
mlflow.set_tracking_uri("http://localhost:5000")
5878

59-
1. Open your browser and go to `http://localhost:5000`
60-
2. You'll be redirected to the Descope login page
61-
3. Authenticate using one of your configured methods
62-
4. You'll be redirected back to MLflow and logged in!
79+
# Start a run - authentication and user context are automatic!
80+
with mlflow.start_run():
81+
mlflow.log_param("alpha", 0.5)
82+
mlflow.log_metric("rmse", 0.8)
83+
```
84+
85+
The plugin automatically:
86+
- Adds authentication headers to all requests
87+
- Injects user context headers (X-Descope-User-ID, X-Descope-Email, etc.)
88+
- Tags runs with user information (descope.user_id, descope.email, etc.)
6389

6490
## What's Next?
6591

92+
### Verify Plugin is Loaded
93+
94+
```bash
95+
# Check that the plugin is registered
96+
python -c "
97+
from importlib.metadata import entry_points
98+
eps = entry_points(group='mlflow.request_auth_provider')
99+
print([ep.name for ep in eps])
100+
"
101+
# Should include 'descope'
102+
```
103+
66104
### Configure Admin Access
67105

68106
By default, all authenticated users have READ access. To grant admin privileges:
69107

70-
1. In your `.env` file, add:
108+
1. Set admin roles in your environment:
71109

72110
```bash
73-
DESCOPE_ADMIN_ROLES=admin,mlflow-admin
111+
export DESCOPE_ADMIN_ROLES="admin,mlflow-admin"
74112
```
75113

76114
2. In Descope Console, go to **Authorization → Roles**
77115
3. Create a role called `admin` or `mlflow-admin`
78116
4. Assign this role to specific users
79117

80-
### Add More Authentication Methods
81-
82-
1. Go to Descope Console → **Authentication → Flows**
83-
2. Edit your flow and add more methods (OAuth, SAML, etc.)
84-
3. **No code changes needed!** Just publish the flow
85-
4. Restart MLflow to see the changes
86-
87118
### Configure Permissions
88119

89-
Create custom permission mapping in your `.env`:
90-
91120
```bash
92121
# Default permission for all users (READ, EDIT, or MANAGE)
93-
DESCOPE_DEFAULT_PERMISSION=READ
122+
export DESCOPE_DEFAULT_PERMISSION="READ"
94123

95124
# Roles that get admin access (MANAGE permission)
96-
DESCOPE_ADMIN_ROLES=admin,mlflow-admin,superuser
125+
export DESCOPE_ADMIN_ROLES="admin,mlflow-admin,superuser"
97126
```
98127

99-
### Production Deployment
128+
### Automatic Run Tagging
100129

101-
For production, use a proper database:
130+
The plugin automatically adds these tags to all runs:
102131

103-
```bash
104-
mlflow server \
105-
--app-name descope-auth \
106-
--backend-store-uri postgresql://user:pass@localhost/mlflow \
107-
--default-artifact-root s3://my-bucket/mlflow \
108-
--host 0.0.0.0 \
109-
--port 5000
110-
```
132+
- `descope.user_id` - User's Descope ID
133+
- `descope.username` - Username
134+
- `descope.email` - User's email
135+
- `descope.name` - User's display name
136+
- `descope.roles` - Comma-separated list of roles
137+
- `descope.permissions` - Comma-separated list of permissions
138+
- `descope.tenants` - Comma-separated list of tenants
111139

112-
### Docker Deployment
113-
114-
Create `docker-compose.yml`:
115-
116-
```yaml
117-
version: "3.8"
118-
119-
services:
120-
mlflow:
121-
image: python:3.11-slim
122-
command: >
123-
sh -c "
124-
pip install mlflow mlflow-descope-auth &&
125-
mlflow server --app-name descope-auth --host 0.0.0.0
126-
"
127-
environment:
128-
- DESCOPE_PROJECT_ID=${DESCOPE_PROJECT_ID}
129-
- DESCOPE_FLOW_ID=sign-up-or-in
130-
ports:
131-
- "5000:5000"
132-
volumes:
133-
- mlflow-data:/mlflow
134-
135-
volumes:
136-
mlflow-data:
137-
```
140+
### Request Headers
138141

139-
Run with:
142+
The plugin adds these headers to MLflow API requests:
140143

141-
```bash
142-
DESCOPE_PROJECT_ID=P2XXXXX docker-compose up
143-
```
144+
- `X-Descope-User-ID`
145+
- `X-Descope-Username`
146+
- `X-Descope-Email`
147+
- `X-Descope-Roles`
148+
- `X-Descope-Permissions`
149+
- `X-Descope-Tenants`
144150

145151
## Troubleshooting
146152

147-
### Login page shows but authentication fails
148-
149-
**Problem**: Web component loads but authentication doesn't work
150-
151-
**Solution**:
152-
153-
1. Check that your `DESCOPE_PROJECT_ID` is correct
154-
2. Ensure your flow exists in Descope Console
155-
3. Check browser console for errors
156-
4. Verify your domain is whitelisted in Descope Console → **Project Settings → Authentication Hosts**
153+
### Plugin not loaded
157154

158-
### Redirected to login in a loop
159-
160-
**Problem**: After successful authentication, you're redirected back to login
155+
**Problem**: Authentication doesn't work
161156

162157
**Solution**:
163158

164-
1. Clear browser cookies
165-
2. Check that cookies are enabled
166-
3. If using HTTPS, ensure your redirect URL uses HTTPS too
167-
4. Check browser console for cookie errors
159+
```bash
160+
# Verify plugin is installed
161+
pip list | grep mlflow-descope-auth
162+
163+
# Check entry points
164+
python -c "
165+
from importlib.metadata import entry_points
166+
eps = entry_points(group='mlflow.request_auth_provider')
167+
print([ep.name for ep in eps])
168+
"
169+
170+
# Ensure MLFLOW_TRACKING_AUTH is set
171+
echo $MLFLOW_TRACKING_AUTH # Should be "descope"
172+
```
168173

169-
### "DESCOPE_PROJECT_ID is required" error
174+
### Authentication fails
170175

171-
**Problem**: MLflow fails to start
176+
**Problem**: Requests fail with authentication errors
172177

173178
**Solution**:
174179

175180
```bash
176-
# Make sure .env file exists in the same directory
177-
cat .env
178-
179-
# Or set environment variable directly
180-
export DESCOPE_PROJECT_ID=P2XXXXX
181-
mlflow server --app-name descope-auth
181+
# Check environment variables
182+
env | grep DESCOPE
183+
184+
# Verify tokens are valid
185+
python -c "
186+
from mlflow_descope_auth import get_descope_client
187+
import os
188+
client = get_descope_client()
189+
result = client.validate_session(os.environ['DESCOPE_SESSION_TOKEN'])
190+
print('✓ Token valid')
191+
"
182192
```
183193

184-
### Port 5000 already in use
194+
### "DESCOPE_PROJECT_ID is required" error
185195

186-
**Problem**: `Address already in use` error
196+
**Problem**: Plugin fails to initialize
187197

188198
**Solution**:
189199

190200
```bash
191-
# Use a different port
192-
mlflow server --app-name descope-auth --port 5001
193-
194-
# Or kill the process using port 5000
195-
lsof -ti:5000 | xargs kill -9
201+
# Set the required environment variable
202+
export DESCOPE_PROJECT_ID=P2XXXXX
203+
export DESCOPE_SESSION_TOKEN="<your-token>"
196204
```
197205

198206
## Need Help?
199207

200208
- **Documentation**: See [README.md](../README.md) for full documentation
209+
- **Architecture**: See [ARCHITECTURE.md](../ARCHITECTURE.md) for technical details
201210
- **Issues**: [GitHub Issues](https://github.com/descope/mlflow-descope-auth/issues)
202211
- **Descope Docs**: [docs.descope.com](https://docs.descope.com/)
203212

204213
## Next Steps
205214

206-
- Read the [Configuration Guide](../README.md#configuration-reference)
207-
- Learn about [Permission Mapping](../README.md#permission-mapping)
208-
- Explore [Advanced Features](../README.md#advanced-features)
209-
- Check out [Docker Examples](../examples/)
215+
- Read the [Configuration Reference](../README.md#configuration-reference)
216+
- Learn about the [Plugin Architecture](../ARCHITECTURE.md)
217+
- Check out the [Docker Examples](../examples/)
210218

211219
Happy MLflow-ing with Descope! 🚀

0 commit comments

Comments
 (0)