Skip to content

Commit 2d852f6

Browse files
authored
Merge pull request #1 from deeleeramone/feature/oauth2-handler
Add oauth2 Flows and Providers
2 parents 5d0612f + 13684d9 commit 2d852f6

55 files changed

Lines changed: 7077 additions & 7542 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

pywry/.pylintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ disable=
2727

2828
[FORMAT]
2929
max-line-length=100
30-
max-module-lines=1000
30+
max-module-lines=2500
3131
expected-line-ending-format=
3232

3333
[BASIC]

pywry/AGENTS.md

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,18 @@ pywry/
144144
│ ├── _factory.py # Factory functions for store instantiation
145145
│ ├── memory.py # In-memory state backends (default)
146146
│ ├── redis.py # Redis-backed state backends
147-
│ ├── types.py # Type definitions (StateBackend, WidgetData, etc.)
148-
│ └── auth.py # Authentication and RBAC utilities
147+
│ ├── types.py # Type definitions (StateBackend, WidgetData, OAuthTokenSet, etc.)
148+
│ ├── auth.py # Authentication and RBAC utilities
149+
│ └── sync_helpers.py # Sync↔async bridging (run_async, wait_for_event)
150+
├── auth/ # OAuth2 authentication system
151+
│ ├── __init__.py # Public exports
152+
│ ├── pkce.py # PKCE challenge generation (RFC 7636)
153+
│ ├── providers.py # OAuthProvider ABC + Google, GitHub, Microsoft, OIDC implementations
154+
│ ├── token_store.py # TokenStore ABC + Memory, Keyring, Redis backends
155+
│ ├── callback_server.py # Ephemeral localhost server for native auth redirects
156+
│ ├── deploy_routes.py # FastAPI /auth/* routes for deploy mode
157+
│ ├── flow.py # AuthFlowManager orchestrator
158+
│ └── session.py # SessionManager with automatic token refresh
149159
├── utils/ # Utility helpers
150160
└── window_manager/ # Window mode implementations
151161
├── controller.py
@@ -1134,6 +1144,72 @@ PYWRY_DEPLOY__DEFAULT_ROLE=viewer
11341144

11351145
---
11361146

1147+
## Authentication & OAuth2
1148+
1149+
PyWry includes a full OAuth2 authentication system that works in both native window mode and deploy mode.
1150+
1151+
### Quick Start (Native Mode)
1152+
1153+
```python
1154+
from pywry import PyWry
1155+
1156+
app = PyWry()
1157+
1158+
# Login with Google (configure via environment variables)
1159+
# PYWRY_OAUTH2__PROVIDER=google
1160+
# PYWRY_OAUTH2__CLIENT_ID=your-client-id
1161+
# PYWRY_OAUTH2__CLIENT_SECRET=your-secret
1162+
result = app.login()
1163+
1164+
if result.success:
1165+
print(f"Logged in! Tokens: {result.tokens.token_type}")
1166+
app.show("<h1>Welcome!</h1>")
1167+
app.block()
1168+
```
1169+
1170+
### Quick Start (Deploy Mode)
1171+
1172+
```bash
1173+
PYWRY_DEPLOY__AUTH_ENABLED=true
1174+
PYWRY_DEPLOY__STATE_BACKEND=redis
1175+
PYWRY_OAUTH2__PROVIDER=github
1176+
PYWRY_OAUTH2__CLIENT_ID=your-client-id
1177+
PYWRY_OAUTH2__CLIENT_SECRET=your-secret
1178+
```
1179+
1180+
Deploy mode automatically mounts `/auth/login`, `/auth/callback`, `/auth/logout`, `/auth/status` routes.
1181+
1182+
### Architecture
1183+
1184+
| Component | File | Purpose |
1185+
|-----------|------|---------|
1186+
| `OAuthProvider` | `auth/providers.py` | ABC for OAuth2 providers (Google, GitHub, Microsoft, OIDC, custom) |
1187+
| `PKCEChallenge` | `auth/pkce.py` | PKCE code challenge generation (RFC 7636) |
1188+
| `TokenStore` | `auth/token_store.py` | ABC for token persistence (Memory, Keyring, Redis) |
1189+
| `OAuthCallbackServer` | `auth/callback_server.py` | Ephemeral localhost HTTP server for native redirect capture |
1190+
| `AuthFlowManager` | `auth/flow.py` | Orchestrates the complete OAuth2 flow |
1191+
| `SessionManager` | `auth/session.py` | Token lifecycle with automatic background refresh |
1192+
| `deploy_routes` | `auth/deploy_routes.py` | FastAPI `/auth/*` routes for production deployments |
1193+
1194+
### OAuth2Settings
1195+
1196+
| Setting | Type | Default | Description |
1197+
|---------|------|---------|-------------|
1198+
| `provider` | `str` | `"custom"` | `google`, `github`, `microsoft`, `oidc`, or `custom` |
1199+
| `client_id` | `str` | `""` | OAuth2 client ID |
1200+
| `client_secret` | `str` | `""` | Client secret (empty for PKCE public clients) |
1201+
| `scopes` | `str` | `"openid email profile"` | Space-separated scopes |
1202+
| `use_pkce` | `bool` | `True` | Enable PKCE for public clients |
1203+
| `token_store_backend` | `str` | `"memory"` | `memory`, `keyring`, or `redis` |
1204+
| `auth_timeout_seconds` | `float` | `120.0` | Max wait for OAuth callback |
1205+
| `refresh_buffer_seconds` | `int` | `60` | Pre-expiry refresh margin |
1206+
1207+
### Frontend Integration
1208+
1209+
When authenticated, `window.__PYWRY_AUTH__` contains `{ user_id, roles, token_type }`. Use `window.pywry.auth.isAuthenticated()`, `.getState()`, `.login()`, `.logout()`, `.onAuthStateChange(cb)`.
1210+
1211+
---
1212+
11371213
## Key Classes Reference
11381214

11391215
### Core Classes

0 commit comments

Comments
 (0)