fastapi-steam-oidc 0.0.1
Steam OIDC for FastAPI
Requires Python: >=3.12
Keywords: fastapi, steam

# pysteam

Steam OpenID Connect Plugin for FastAPI

## Features

- Steam OpenID Connect (OIDC) integration for authentication
- Session-based user management using SessionMiddleware
- Callbacks for on_login and on_logout to customize user handling behavior
- Pre-built routes for login, logout
- Extendable and configurable settings

---

## Installation

```Python
pip install pysteam
```

---

## Quick Start

Here's an example of how you can configure PySteam and use Steam as an OpenID Provider

### 1. Configure pysteam FastAPI settings

```Python
oidc_app_settings = OidcAppSettings(             # pysteam routes that will be included in FastAPI application
    base_url="http://localhost:8000",            # Base application url
    login_url="/login",                          # Login url
    logout_url="/logout",                        # Logout url
    callback_url="/callback",                    # Callback verification url
    post_callback_url="/me",                     # Post callback redirect
    auth_router_prefix="/steam",                 # OIDC router prefix (e.g. '/steam') | This prefixes supplied urls above
)
```

---

### 2. Configure pysteam OIDC settings

```Python
oidc_session_settings = OidcSessionSettings(      # OIDC settings
    secret_key="test",                            # Secret key
    session_cookie="steam_session",               # Session cookie name
    max_age=(60*60*24*14),                        # Session cookie max age (e.g. (60*60*24*14) = 14 days in seconds)
    same_site="lax",                              # CSRF same site
    https_only=False,                             # https_only (True in prod)
    csrf_state_ttl_seconds=600,                   # CSRF TTL
    openid_nonce_ttl_seconds=600,                 # NONCE TTL
    openid_nonce_clock_skew_seconds=300           # NONCE TTL skew
)
```

---

### 3. Create pysteam settings

```Python
pysteam_settings = PySteamSettings(
    app_config=oidc_app_settings,
    session_config=oidc_session_settings
)
```

---

### 4. Set up FastAPI application

```Python
app = FastAPI()
oidc = SteamOIDC(app, pysteam_settings)
app.include_router(oidc.router)
```

---

### 5. Add login and logout callbacks (optional)

```Python
@oidc.on_login
async def login_callback(steamid):    # Session steamid will be passed into the callback
  print(f"User: {steamid)")
```

```Python
@oidc.on_logout
async def logout_callback():          # Nothing will be passed to this as pysteam will clear the session
  print("Logged out!")
```

---

### 5. Secure protected routes

Use the `get_logged_user` dependency to secure your endpoints and access the currently authorized user.

```Python
from fastapi import Depends
from pysteam import get_logged_user

@app.get("/protected")
async def protected_route(steamid = Depends(get_logged_user):
  return {"steamid": steamid}
```

Exception raised for unauthorized users:

- 401 Unauthorized if the user is not authenticated

---

## Pydantic Models

```Python
class PySteamSettings(BaseModel):
    app_config: OidcAppSettings
    session_config: OidcSessionSettings
```

```Python
class OidcAppSettings(BaseModel):
    base_url: str = Field(title="API Base URL (e.g 'localhost:8000')")
    login_url: str = Field(title="Login path (e.g. '/login')", default="/login")
    logout_url: str = Field(title="Logout path (e.g. '/logout')", default="/logout")
    callback_url: str = Field(title="OpenID return to path (e.g. '/callback')", default="/callback")
    post_callback_url: str = Field(title="URL Redirected to after successful login", default="/me")
    auth_router_prefix: str = Field(title="Auth router prefix (e.g '/auth', '/auth/steam', '/steam')")
```

```Python
class OidcSessionSettings(BaseModel):
    secret_key: str = Field(title="Session secret key", default="secretkey")
    session_cookie: str = Field(title="Session name", default="steam_session")
    max_age: int = Field(title="Session max age in seconds", default=(60 * 60 * 24 * 14))
    same_site: str = Field(title="CSRF", default="lax")
    https_only: bool = Field(title="https_only", default=False)
    csrf_state_ttl_seconds: int = Field(title="CSRF TTL Seconds", default=600)
    openid_nonce_ttl_seconds: int = Field(title="NONCE TTL Seconds", default=600)
    openid_nonce_clock_skew_seconds: int = Field(title="NONCE Skew Seconds", default=300)
```