mirror of
https://github.com/stack-auth/stack.git
synced 2026-07-20 21:29:36 +08:00
docs: add comprehensive README for python sdk
Covers installation, quick start, async usage, authentication with FastAPI example, error handling, teams, self-hosted config, full API reference, and development/testing instructions.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Stack Auth Python SDK
|
||||
|
||||
Python SDK for [Stack Auth](https://stack-auth.com) - authentication, user management, and team management for your Python backend.
|
||||
Python SDK for [Stack Auth](https://stack-auth.com) — the open-source authentication platform. Provides `StackServerApp` for server-side user management, team operations, JWT verification, and more.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -15,13 +15,204 @@ from stack_auth import StackServerApp
|
||||
|
||||
app = StackServerApp(
|
||||
project_id="your-project-id",
|
||||
secret_server_key="your-secret-key",
|
||||
secret_server_key="your-secret-server-key",
|
||||
)
|
||||
|
||||
# Verify a request's access token
|
||||
user = await app.authenticate_request(request)
|
||||
# List users
|
||||
users = app.list_users(limit=10)
|
||||
for user in users.items:
|
||||
print(f"{user.display_name} ({user.primary_email})")
|
||||
|
||||
# Create a user
|
||||
user = app.create_user(
|
||||
primary_email="[email protected]",
|
||||
password="securepassword",
|
||||
display_name="Jane Doe",
|
||||
)
|
||||
|
||||
# Get a user
|
||||
user = app.get_user("user-id")
|
||||
|
||||
# Update a user
|
||||
updated = app.update_user("user-id", display_name="New Name")
|
||||
|
||||
# Delete a user
|
||||
app.delete_user("user-id")
|
||||
```
|
||||
|
||||
## Async Support
|
||||
|
||||
Every method has an async equivalent via `AsyncStackServerApp`:
|
||||
|
||||
```python
|
||||
from stack_auth import AsyncStackServerApp
|
||||
|
||||
app = AsyncStackServerApp(
|
||||
project_id="your-project-id",
|
||||
secret_server_key="your-secret-server-key",
|
||||
)
|
||||
|
||||
user = await app.get_user("user-id")
|
||||
users = await app.list_users(limit=10)
|
||||
team = await app.create_team(display_name="Engineering")
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
Verify incoming request tokens without framework-specific middleware:
|
||||
|
||||
```python
|
||||
from stack_auth._auth import sync_authenticate_request
|
||||
from stack_auth._jwt import SyncJWKSFetcher
|
||||
|
||||
fetcher = SyncJWKSFetcher(
|
||||
project_id="your-project-id",
|
||||
base_url="https://api.stack-auth.com",
|
||||
)
|
||||
|
||||
# Works with any object that has a .headers mapping
|
||||
result = sync_authenticate_request(request, fetcher=fetcher)
|
||||
|
||||
if result.status == "authenticated":
|
||||
print(f"User: {result.user_id}")
|
||||
else:
|
||||
print("Not authenticated")
|
||||
```
|
||||
|
||||
### FastAPI Example
|
||||
|
||||
```python
|
||||
from fastapi import Depends, HTTPException, Request
|
||||
from stack_auth._auth import sync_authenticate_request
|
||||
from stack_auth._jwt import SyncJWKSFetcher
|
||||
|
||||
fetcher = SyncJWKSFetcher(project_id="...", base_url="https://api.stack-auth.com")
|
||||
|
||||
def get_user_id(request: Request) -> str:
|
||||
result = sync_authenticate_request(request, fetcher=fetcher)
|
||||
if result.status != "authenticated":
|
||||
raise HTTPException(status_code=401)
|
||||
return result.user_id
|
||||
|
||||
@app.get("/protected")
|
||||
def protected_route(user_id: str = Depends(get_user_id)):
|
||||
return {"user_id": user_id}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
All API errors raise typed exceptions:
|
||||
|
||||
```python
|
||||
from stack_auth.errors import (
|
||||
StackAuthError,
|
||||
AuthenticationError,
|
||||
NotFoundError,
|
||||
ValidationError,
|
||||
)
|
||||
|
||||
try:
|
||||
user = app.get_user("invalid-id")
|
||||
except NotFoundError as e:
|
||||
print(f"Not found: {e.message}")
|
||||
except AuthenticationError as e:
|
||||
print(f"Auth failed: {e.code}")
|
||||
except StackAuthError as e:
|
||||
print(f"API error: {e.code} - {e.message}")
|
||||
```
|
||||
|
||||
## Teams
|
||||
|
||||
```python
|
||||
# Create a team
|
||||
team = app.create_team(
|
||||
display_name="Engineering",
|
||||
creator_user_id="user-id",
|
||||
)
|
||||
|
||||
# List teams
|
||||
teams = app.list_teams(user_id="user-id")
|
||||
|
||||
# Manage members
|
||||
app.add_team_member(team_id=team.id, user_id="another-user-id")
|
||||
profiles = app.list_team_member_profiles(team_id=team.id)
|
||||
|
||||
# Permissions
|
||||
app.grant_team_permission(
|
||||
team_id=team.id,
|
||||
user_id="user-id",
|
||||
permission_id="admin",
|
||||
)
|
||||
```
|
||||
|
||||
## Self-Hosted
|
||||
|
||||
Point to your self-hosted Stack Auth instance:
|
||||
|
||||
```python
|
||||
app = StackServerApp(
|
||||
project_id="your-project-id",
|
||||
secret_server_key="your-secret-key",
|
||||
base_url="https://your-stack-auth.example.com",
|
||||
)
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### StackServerApp / AsyncStackServerApp
|
||||
|
||||
**Constructor:**
|
||||
- `project_id` (str) — Your Stack Auth project ID
|
||||
- `secret_server_key` (str) — Server secret key from the dashboard
|
||||
- `base_url` (str, optional) — API base URL (default: `https://api.stack-auth.com`)
|
||||
- `publishable_client_key` (str, optional) — Required for projects with `requirePublishableClientKey`
|
||||
- `token_store` (optional) — Token storage strategy
|
||||
|
||||
**User methods:** `get_user`, `list_users`, `create_user`, `update_user`, `delete_user`, `get_user_by_api_key`, `get_partial_user`
|
||||
|
||||
**Team methods:** `get_team`, `list_teams`, `create_team`, `update_team`, `delete_team`, `get_team_by_api_key`, `add_team_member`, `remove_team_member`, `list_team_member_profiles`, `get_team_member_profile`, `send_team_invitation`, `list_team_invitations`, `revoke_team_invitation`
|
||||
|
||||
**Permission methods:** `grant_team_permission`, `revoke_team_permission`, `list_team_permissions`, `grant_user_permission`, `revoke_user_permission`, `list_user_permissions`
|
||||
|
||||
**Session methods:** `list_sessions`, `get_session`, `revoke_session`
|
||||
|
||||
**Contact channel methods:** `send_contact_channel_verification`, `verify_contact_channel`, `check_contact_channel_verification`
|
||||
|
||||
**API key methods:** `create_user_api_key`, `list_user_api_keys`, `revoke_user_api_key`, `create_team_api_key`, `list_team_api_keys`, `revoke_team_api_key`, `check_api_key`
|
||||
|
||||
**OAuth methods:** `list_oauth_providers`, `create_oauth_provider`, `get_oauth_provider`, `list_connected_accounts`
|
||||
|
||||
**Payment methods:** `list_products`, `get_item`, `grant_product`, `cancel_subscription`
|
||||
|
||||
**Email methods:** `send_email`, `get_email_delivery_stats`
|
||||
|
||||
**Data vault:** `get_data_vault_store` → returns `DataVaultStore` with `get`, `set`, `delete`, `list_keys`
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
# Clone the repo
|
||||
git clone https://github.com/ejirocodes/stack-auth.git
|
||||
cd stack-auth/sdks/implementations/python
|
||||
|
||||
# Install in dev mode
|
||||
pip install -e ".[dev]"
|
||||
|
||||
# Run unit tests (no server needed)
|
||||
python3 -m pytest tests/ -v
|
||||
|
||||
# Run E2E tests (requires running Stack Auth)
|
||||
# First: pnpm start-deps && pnpm dev (from monorepo root)
|
||||
STACK_E2E=1 python3 -m pytest tests/test_e2e.py -v -s
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.10+
|
||||
- Python >= 3.10
|
||||
- httpx
|
||||
- PyJWT[crypto]
|
||||
- pydantic >= 2.7
|
||||
|
||||
## License
|
||||
|
||||
MIT — same as [Stack Auth](https://github.com/stack-auth/stack-auth).
|
||||
|
||||
Reference in New Issue
Block a user