Skip to content

Commit 7806a5c

Browse files
committed
add documentation and login example
1 parent c65f42b commit 7806a5c

File tree

2 files changed

+438
-0
lines changed

2 files changed

+438
-0
lines changed

docs/sdk/AUTHENTICATION.md

Lines changed: 369 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,369 @@
1+
# DataSpace SDK Authentication Guide
2+
3+
This guide explains how to authenticate with the DataSpace SDK using username/password with automatic token management.
4+
5+
## Table of Contents
6+
7+
- [Quick Start](#quick-start)
8+
- [Authentication Methods](#authentication-methods)
9+
- [Automatic Token Management](#automatic-token-management)
10+
- [Configuration](#configuration)
11+
- [Error Handling](#error-handling)
12+
- [Best Practices](#best-practices)
13+
14+
## Quick Start
15+
16+
### Username/Password Login (Recommended)
17+
18+
```python
19+
from dataspace_sdk import DataSpaceClient
20+
21+
# Initialize with Keycloak configuration
22+
client = DataSpaceClient(
23+
base_url="https://dataspace.civicdatalab.in",
24+
keycloak_url="https://opub-kc.civicdatalab.in",
25+
keycloak_realm="DataSpace",
26+
keycloak_client_id="dataspace"
27+
)
28+
29+
# Login once - credentials stored for auto-refresh
30+
user_info = client.login(
31+
username="[email protected]",
32+
password="your-password"
33+
)
34+
35+
# Now use the client - tokens auto-refresh!
36+
datasets = client.datasets.search(query="health")
37+
```
38+
39+
## Authentication Methods
40+
41+
### 1. Username/Password (Recommended)
42+
43+
Best for:
44+
- Scripts and automation
45+
- Long-running applications
46+
- Development and testing
47+
48+
```python
49+
client = DataSpaceClient(
50+
base_url="https://dataspace.civicdatalab.in",
51+
keycloak_url="https://opub-kc.civicdatalab.in",
52+
keycloak_realm="DataSpace",
53+
keycloak_client_id="dataspace"
54+
)
55+
56+
user_info = client.login(
57+
username="[email protected]",
58+
password="secret"
59+
)
60+
```
61+
62+
**Features:**
63+
- ✅ Automatic token refresh
64+
- ✅ Automatic re-login if refresh fails
65+
- ✅ No manual token management needed
66+
- ✅ Credentials stored securely in memory
67+
68+
### 2. Pre-obtained Keycloak Token
69+
70+
Best for:
71+
- When you already have a token from another source
72+
- Browser-based applications
73+
- SSO integrations
74+
75+
```python
76+
client = DataSpaceClient(base_url="https://dataspace.civicdatalab.in")
77+
78+
user_info = client.login_with_token(keycloak_token="eyJhbGci...")
79+
```
80+
81+
**Note:** This method does NOT support automatic token refresh or re-login.
82+
83+
## Automatic Token Management
84+
85+
The SDK automatically handles token expiration and refresh:
86+
87+
### How It Works
88+
89+
1. **Login**: You provide username/password once
90+
2. **Token Storage**: SDK stores credentials securely in memory
91+
3. **Auto-Refresh**: When token expires (within 30 seconds), SDK automatically refreshes it
92+
4. **Auto-Relogin**: If refresh fails, SDK automatically re-authenticates with stored credentials
93+
5. **Transparent**: All of this happens automatically - you don't need to do anything!
94+
95+
### Example: Long-Running Script
96+
97+
```python
98+
import time
99+
from dataspace_sdk import DataSpaceClient
100+
101+
client = DataSpaceClient(
102+
base_url="https://dataspace.civicdatalab.in",
103+
keycloak_url="https://opub-kc.civicdatalab.in",
104+
keycloak_realm="DataSpace",
105+
keycloak_client_id="dataspace"
106+
)
107+
108+
# Login once
109+
client.login(username="[email protected]", password="secret")
110+
111+
# Run for hours - tokens auto-refresh!
112+
while True:
113+
datasets = client.datasets.search(query="health")
114+
print(f"Found {len(datasets.get('results', []))} datasets")
115+
116+
# Sleep for 10 minutes
117+
time.sleep(600)
118+
119+
# SDK automatically refreshes tokens as needed
120+
# No manual intervention required!
121+
```
122+
123+
## Configuration
124+
125+
### Keycloak Configuration
126+
127+
You need these details from your Keycloak setup:
128+
129+
```python
130+
client = DataSpaceClient(
131+
base_url="https://dataspace.civicdatalab.in", # DataSpace API URL
132+
keycloak_url="https://opub-kc.civicdatalab.in", # Keycloak server URL
133+
keycloak_realm="DataSpace", # Realm name
134+
keycloak_client_id="dataspace", # Client ID
135+
keycloak_client_secret="optional-secret" # Only for confidential clients
136+
)
137+
```
138+
139+
### Finding Your Keycloak Details
140+
141+
1. **Keycloak URL**: Your Keycloak server address
142+
2. **Realm**: Usually shown in Keycloak admin console
143+
3. **Client ID**: Found in Keycloak → Clients → Your Client
144+
4. **Client Secret**: Only needed if client is "confidential" (check Access Type in Keycloak)
145+
146+
### Environment Variables (Recommended)
147+
148+
Store credentials securely:
149+
150+
```python
151+
import os
152+
from dataspace_sdk import DataSpaceClient
153+
154+
client = DataSpaceClient(
155+
base_url=os.getenv("DATASPACE_API_URL"),
156+
keycloak_url=os.getenv("KEYCLOAK_URL"),
157+
keycloak_realm=os.getenv("KEYCLOAK_REALM"),
158+
keycloak_client_id=os.getenv("KEYCLOAK_CLIENT_ID"),
159+
keycloak_client_secret=os.getenv("KEYCLOAK_CLIENT_SECRET") # Optional
160+
)
161+
162+
client.login(
163+
username=os.getenv("DATASPACE_USERNAME"),
164+
password=os.getenv("DATASPACE_PASSWORD")
165+
)
166+
```
167+
168+
Create a `.env` file:
169+
170+
```bash
171+
DATASPACE_API_URL=https://dataspace.civicdatalab.in
172+
KEYCLOAK_URL=https://opub-kc.civicdatalab.in
173+
KEYCLOAK_REALM=DataSpace
174+
KEYCLOAK_CLIENT_ID=dataspace
175+
176+
DATASPACE_PASSWORD=your-password
177+
```
178+
179+
## Error Handling
180+
181+
### Authentication Errors
182+
183+
```python
184+
from dataspace_sdk import DataSpaceClient
185+
from dataspace_sdk.exceptions import DataSpaceAuthError
186+
187+
client = DataSpaceClient(
188+
base_url="https://dataspace.civicdatalab.in",
189+
keycloak_url="https://opub-kc.civicdatalab.in",
190+
keycloak_realm="DataSpace",
191+
keycloak_client_id="dataspace"
192+
)
193+
194+
try:
195+
user_info = client.login(
196+
username="[email protected]",
197+
password="wrong-password"
198+
)
199+
except DataSpaceAuthError as e:
200+
print(f"Login failed: {e}")
201+
print(f"Status code: {e.status_code}")
202+
print(f"Response: {e.response}")
203+
```
204+
205+
### Common Errors
206+
207+
| Error | Cause | Solution |
208+
|-------|-------|----------|
209+
| `Keycloak configuration missing` | Missing keycloak_url, realm, or client_id | Provide all required Keycloak parameters |
210+
| `Keycloak login failed: invalid_grant` | Wrong username/password | Check credentials |
211+
| `Keycloak login failed: invalid_client` | Wrong client_id or client requires consent | Check client_id or disable consent in Keycloak |
212+
| `Resource not found` | Wrong Keycloak URL or realm | Verify keycloak_url and realm name |
213+
| `Not authenticated` | Trying to use API before login | Call `client.login()` first |
214+
215+
### Checking Authentication Status
216+
217+
```python
218+
# Check if authenticated
219+
if client.is_authenticated():
220+
print("Authenticated!")
221+
else:
222+
print("Not authenticated")
223+
224+
# Get current user info
225+
user = client.user
226+
if user:
227+
print(f"Logged in as: {user['username']}")
228+
```
229+
230+
## Best Practices
231+
232+
### 1. Use Environment Variables
233+
234+
Never hardcode credentials:
235+
236+
```python
237+
# ❌ Bad
238+
client.login(username="[email protected]", password="secret123")
239+
240+
# ✅ Good
241+
client.login(
242+
username=os.getenv("DATASPACE_USERNAME"),
243+
password=os.getenv("DATASPACE_PASSWORD")
244+
)
245+
```
246+
247+
### 2. Login Once, Use Everywhere
248+
249+
```python
250+
# ✅ Good - Login once at startup
251+
client = DataSpaceClient(...)
252+
client.login(username=..., password=...)
253+
254+
# Use client throughout your application
255+
# Tokens auto-refresh!
256+
datasets = client.datasets.search(...)
257+
models = client.aimodels.search(...)
258+
```
259+
260+
### 3. Handle Errors Gracefully
261+
262+
```python
263+
from dataspace_sdk.exceptions import DataSpaceAuthError
264+
265+
try:
266+
client.login(username=username, password=password)
267+
except DataSpaceAuthError as e:
268+
logger.error(f"Authentication failed: {e}")
269+
# Handle error appropriately
270+
sys.exit(1)
271+
```
272+
273+
### 4. Use Confidential Clients for Production
274+
275+
For production applications, use a confidential client with client_secret:
276+
277+
```python
278+
client = DataSpaceClient(
279+
base_url="https://dataspace.civicdatalab.in",
280+
keycloak_url="https://opub-kc.civicdatalab.in",
281+
keycloak_realm="DataSpace",
282+
keycloak_client_id="dataspace-prod",
283+
keycloak_client_secret=os.getenv("KEYCLOAK_CLIENT_SECRET")
284+
)
285+
```
286+
287+
### 5. Don't Store Passwords in Code
288+
289+
```python
290+
# ❌ Bad
291+
PASSWORD = "secret123"
292+
293+
# ✅ Good - Use environment variables
294+
password = os.getenv("DATASPACE_PASSWORD")
295+
296+
# ✅ Better - Use secrets management
297+
from your_secrets_manager import get_secret
298+
password = get_secret("dataspace_password")
299+
```
300+
301+
## Advanced Usage
302+
303+
### Manual Token Refresh
304+
305+
While automatic refresh is recommended, you can manually refresh:
306+
307+
```python
308+
# Get new access token
309+
new_token = client.refresh_token()
310+
print(f"New token: {new_token}")
311+
```
312+
313+
### Get Current Access Token
314+
315+
```python
316+
# Get current token (e.g., to pass to another service)
317+
token = client.access_token
318+
print(f"Current token: {token}")
319+
```
320+
321+
### Ensure Authentication
322+
323+
Force authentication check and auto-relogin if needed:
324+
325+
```python
326+
# This will auto-relogin if not authenticated
327+
client._auth.ensure_authenticated()
328+
```
329+
330+
## Troubleshooting
331+
332+
### Token Keeps Expiring
333+
334+
If you're experiencing frequent token expiration:
335+
336+
1. **Check token lifetime**: Keycloak admin → Realm Settings → Tokens → Access Token Lifespan
337+
2. **Verify auto-refresh**: SDK automatically refreshes 30 seconds before expiration
338+
3. **Check credentials**: Ensure username/password are stored correctly
339+
340+
### "Resource not found" Error
341+
342+
This usually means wrong Keycloak URL:
343+
344+
```python
345+
# Try with /auth prefix
346+
keycloak_url="https://opub-kc.civicdatalab.in/auth"
347+
348+
# Or without
349+
keycloak_url="https://opub-kc.civicdatalab.in"
350+
351+
# Test in browser:
352+
# https://opub-kc.civicdatalab.in/auth/realms/DataSpace/.well-known/openid-configuration
353+
```
354+
355+
### "Client requires user consent" Error
356+
357+
In Keycloak admin console:
358+
359+
1. Go to Clients → your client
360+
2. Find "Consent Required" setting
361+
3. Set to OFF
362+
4. Save
363+
364+
## Next Steps
365+
366+
- [Quick Start Guide](QUICKSTART.md)
367+
- [Full SDK Documentation](README.md)
368+
- [Examples](../../examples/)
369+
- [API Reference](API_REFERENCE.md)

0 commit comments

Comments
 (0)