Metadata-Version: 2.4
Name: scalio-identity
Version: 0.1.0
Summary: Sign-in through Scalio ID, Entra app roles and second factor, shared by the Scalio apps
License: Proprietary
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: PyJWT[crypto]>=2.10
Requires-Dist: httpx>=0.27
Provides-Extra: mfa
Requires-Dist: pyotp>=2.9; extra == "mfa"
Requires-Dist: webauthn>=2.0; extra == "mfa"
Provides-Extra: testing
Requires-Dist: cbor2>=5.6; extra == "testing"
Requires-Dist: cryptography>=42; extra == "testing"
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
Requires-Dist: pyotp>=2.9; extra == "dev"
Requires-Dist: webauthn>=2.0; extra == "dev"
Requires-Dist: cbor2>=5.6; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"

# scalio-identity

Identity helpers shared by the Scalio apps Nexus, Citadel, Rosetta and Foundry. Decisions: scalio-docs ADR 0028
(`idm/I1`–`I12`), concept `concepts/central-user-management.md`. Protocol of the broker: scalio-docs
`interfaces/scalio-id-oidc.md`.

```
pip install "scalio-identity[mfa]"          # app
pip install "scalio-identity[mfa,testing]"  # app tests
```

| Module | What it does |
| --- | --- |
| `scalio_identity.broker` | Sign-in through Scalio ID: `Broker.from_env()`, `Flow.new()`, `authorize_url()`, `redeem()` → `Identity`; `check_binding()` refuses another organisation (`SCALIO_ORG_ID`) or tenant |
| `scalio_identity.roles` | `RoleMap("Nexus", {"Admin": "admin", ...})`: Entra app roles (`Nexus.Admin`) → app role, unknown = no rights |
| `scalio_identity.accounts` | Account lookup by Scalio ID subject, then Microsoft tenant + object id; e-mail only for a one-time link |
| `scalio_identity.mfa` | TOTP (replay safe), backup codes, passkeys (WebAuthn, user verification required) |
| `scalio_identity.testing` | `FakeBroker` (Scalio ID in memory, `httpx.MockTransport`) and `SoftKey` (software passkey) |

The app keeps its routes, state storage, sessions and accounts; this package only checks.

## Settings of an app

| Variable | Meaning |
| --- | --- |
| `SCALIO_ID_ISSUER` | broker, e.g. `https://sso.scaliocloud.com`; empty = Scalio ID off |
| `SCALIO_ID_CLIENT_ID` | the app's origin; default from the app's own URL |
| `SCALIO_ORG_ID` | Scalio organisation of a SaaS instance (set at provisioning); empty on self-hosted |

## Development

```
pip install -e ".[dev]"
ruff check . && pytest -q
```

Release: bump `pyproject.toml` and `__version__`, CHANGELOG line, merge, then "Freigeben" in the Scalio Dev
cockpit (or Actions → Publish with the version). PyPI trusted publishing, environment `pypi`, no token.
