Metadata-Version: 2.4
Name: ecc-auth
Version: 0.2.0
Summary: Shared Xinghe OAuth2 authentication SDK for ECC projects
Project-URL: Homepage, https://github.com/early-chinese-civilization/ecc-auth
Project-URL: Source, https://github.com/early-chinese-civilization/ecc-auth
Project-URL: Issues, https://github.com/early-chinese-civilization/ecc-auth/issues
Author: Early Chinese Civilization
Keywords: authentication,ecc,fastapi,oauth2,xinghe
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Security
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: fastapi>=0.115
Requires-Dist: httpx>=0.28
Requires-Dist: starlette>=0.40
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ty; extra == 'dev'
Requires-Dist: uvicorn>=0.34; extra == 'dev'
Description-Content-Type: text/markdown

# ecc-auth

`ecc-auth` is a small shared authentication SDK for ECC Python services that use
星河 OAuth2 authorization-code login with FastAPI.

Version `0.2.0` is a breaking Xinghe-only release. It implements only the
current Xinghe browser login and session model.

It provides:

- 星河 OAuth2 configuration via `XingheOAuthConfig`
- Standard FastAPI auth routes via `create_auth_router`
- Current-user dependencies via `get_current_user` and `get_current_user_optional`
- Server-side session refresh through Xinghe refreshToken
- User identity validation through Xinghe userInfo
- Xinghe identity normalization for `userId`, `name`, `tel`, `email`,
  `organization`, and `avatarUrl`

## Installation

Once published to PyPI:

```bash
pip install ecc-auth
```

Or with `uv`:

```bash
uv add ecc-auth
```

## Quick Start

```python
from fastapi import FastAPI

from ecc_auth import (
    AuthSessionMiddleware,
    XingheOAuthConfig,
    create_auth_router,
    init_dependencies,
)

app = FastAPI()
app.add_middleware(AuthSessionMiddleware)

config = XingheOAuthConfig(
    base_url="https://staging-aistudio.ai4s.infly.tech/partner/sso/auth-center",
    client_id="auth-server-zhwm",
    client_secret="inject-from-secret-manager",
    redirect_uri="http://localhost:2026/api/auth/callback",
    tls_insecure=False,
)

init_dependencies(config)
app.include_router(create_auth_router(config), prefix="/api/auth")
```

For apps served under a public sub-path, pass that path to the router so the
generated callback and post-login URLs match the externally reachable app:

```python
app.include_router(
    create_auth_router(config, public_base_path="/deer-flow"),
    prefix="/api/auth",
)
```

## Environment

`XingheOAuthConfig()` reads these environment variables by default:

- `XINGHE_OAUTH_BASE_URL`
- `XINGHE_OAUTH_CLIENT_ID`
- `XINGHE_OAUTH_CLIENT_SECRET`
- `XINGHE_OAUTH_REDIRECT_URI` (optional)
- `XINGHE_OAUTH_AUTHORIZE_PATH` (optional)
- `XINGHE_OAUTH_TOKEN_PATH` (optional)
- `XINGHE_OAUTH_REFRESH_PATH` (optional)
- `XINGHE_OAUTH_USERINFO_PATH` (optional)
- `XINGHE_OAUTH_TOKEN_CLIENT_AUTH_METHOD` (optional, default `basic`)
- `XINGHE_OAUTH_REFRESH_CLIENT_AUTH_METHOD` (optional, default `body`)
- `XINGHE_OAUTH_SCOPE` (optional)
- `XINGHE_OAUTH_FORCE_LOGIN_PARAMS` (optional)
- `XINGHE_OAUTH_TLS_INSECURE` (optional, default `false`)

## Callback Error Contract

When `/api/auth/callback` cannot complete, `ecc-auth` redirects back to the app
origin with a stable `?error=<code>` query parameter.

Current callback error codes:

- `missing_state`
- `invalid_state`
- `missing_code`
- `csrf_mismatch`
- `authorization_failed`
- `token_exchange_failed`
- `callback_upstream_failed`
- `token_validation_failed`
- `userinfo_unavailable`
- `user_sync_failed`
- `callback_failed`

Consumer apps should map these codes to user-facing copy instead of exposing raw
exception text.

## Development

Build the package locally:

```bash
uv build
```

Run tests:

```bash
uv run pytest
```

## Publishing

Recommended release flow:

1. Bump `version` in `pyproject.toml`.
2. Commit and push the change.
3. Create a GitHub release.
4. Let the workflow build and publish the package to PyPI.
