Files
mcias/clients/python
Kyle Isom 39d9ffb79a Add service-context login policy enforcement
Services send service_name and tags in POST /v1/auth/login.
MCIAS evaluates auth:login policy with these as the resource
context after credentials are verified, enabling rules like:
  deny guest/viewer human accounts from env:restricted services
  deny guest accounts from specific named services

- loginRequest: add ServiceName and Tags fields
- handleLogin: evaluate policy after credential+TOTP check;
  policy deny returns 403 (not 401) to distinguish access
  restriction from bad credentials
- Go client: Options.ServiceName/Tags stored on Client,
  sent automatically in every Login() call
- Python client: service_name/tags on __init__, sent in login()
- Rust client: ClientOptions.service_name/tags, LoginRequest
  fields, Client stores and sends them in login()
- openapi.yaml: document service_name/tags request fields
  and 403 response for policy-denied logins
- engineering-standards.md: document service_name/tags in
  [mcias] config section with policy examples

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 21:11:35 -07:00
..

mcias-client (Python)

Python client library for the MCIAS identity and access management API.

Requirements

  • Python 3.11+
  • httpx >= 0.27

Installation

pip install .
# or in development mode:
pip install -e ".[dev]"

Quick Start

from mcias_client import Client

# Connect to the MCIAS server.
with Client("https://auth.example.com") as client:
    # Authenticate.
    token, expires_at = client.login("alice", "s3cret")
    print(f"token expires at {expires_at}")

    # The token is stored in the client automatically.
    accounts = client.list_accounts()

    # Revoke the token when done (also called automatically on context exit).
    client.logout()

Custom CA Certificate

client = Client(
    "https://auth.example.com",
    ca_cert_path="/etc/mcias/ca.pem",
)

Error Handling

All methods raise typed exceptions on error:

from mcias_client import (
    MciasAuthError,
    MciasForbiddenError,
    MciasNotFoundError,
    MciasInputError,
    MciasConflictError,
    MciasServerError,
)

try:
    client.login("alice", "wrongpass")
except MciasAuthError as e:
    print(f"auth failed ({e.status_code}): {e.message}")
except MciasForbiddenError as e:
    print(f"forbidden: {e.message}")
except MciasNotFoundError as e:
    print(f"not found: {e.message}")
except MciasInputError as e:
    print(f"bad input: {e.message}")
except MciasConflictError as e:
    print(f"conflict: {e.message}")
except MciasServerError as e:
    print(f"server error {e.status_code}: {e.message}")

All exception types are subclasses of MciasError, which has attributes:

  • status_code: int — HTTP status code
  • message: str — server error message

Thread Safety

Client is not thread-safe. Each thread should use its own Client instance.

Running Tests

pip install -e ".[dev]"
pytest tests/ -q
mypy mcias_client/ tests/
ruff check mcias_client/ tests/