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>
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 codemessage: 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/