mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-05-19 20:35:13 +02:00
feat: add no-auth IAM regime as a drop-in replacement for iam-svc (#933)
Adds `no-auth-svc`, a lightweight IAM service that permits all access unconditionally — no database, no bootstrap, no signing keys. Deploy it in place of `iam-svc` for development, demos, and single-user setups where authentication overhead is unwanted. The gateway no longer hard-codes a 401 on missing credentials. Instead it asks the IAM regime via a new `authenticate-anonymous` operation whether token-free access is allowed. This keeps the gateway regime-agnostic: `iam-svc` rejects anonymous auth (preserving existing security), while `no-auth-svc` grants it with a configurable default user and workspace. Includes a tech spec (docs/tech-specs/no-auth-regime.md) and tests that pin the safety boundary — malformed tokens never fall through to the anonymous path, and a contract test ensures the full iam-svc always rejects `authenticate-anonymous`.
This commit is contained in:
parent
ab83c81d8a
commit
da7d10e995
16 changed files with 876 additions and 32 deletions
|
|
@ -62,12 +62,6 @@ class AsyncSocketClient:
|
|||
if self._connected:
|
||||
return
|
||||
|
||||
if not self.token:
|
||||
raise ProtocolException(
|
||||
"AsyncSocketClient requires a token for first-frame "
|
||||
"auth against /api/v1/socket"
|
||||
)
|
||||
|
||||
ws_url = self._build_ws_url()
|
||||
self._connect_cm = websockets.connect(
|
||||
ws_url, ping_interval=20, ping_timeout=self.timeout
|
||||
|
|
@ -79,7 +73,7 @@ class AsyncSocketClient:
|
|||
# reader task so the response isn't consumed by the reader's
|
||||
# id-based routing.
|
||||
await self._socket.send(json.dumps({
|
||||
"type": "auth", "token": self.token,
|
||||
"type": "auth", "token": self.token or "",
|
||||
}))
|
||||
try:
|
||||
raw = await asyncio.wait_for(
|
||||
|
|
|
|||
|
|
@ -137,12 +137,6 @@ class SocketClient:
|
|||
if self._connected:
|
||||
return
|
||||
|
||||
if not self.token:
|
||||
raise ProtocolException(
|
||||
"SocketClient requires a token for first-frame auth "
|
||||
"against /api/v1/socket"
|
||||
)
|
||||
|
||||
ws_url = self._build_ws_url()
|
||||
self._connect_cm = websockets.connect(
|
||||
ws_url, ping_interval=20, ping_timeout=self.timeout
|
||||
|
|
@ -153,7 +147,7 @@ class SocketClient:
|
|||
# auth-ok / auth-failed response isn't consumed by the reader
|
||||
# loop's id-based routing.
|
||||
await self._socket.send(json.dumps({
|
||||
"type": "auth", "token": self.token,
|
||||
"type": "auth", "token": self.token or "",
|
||||
}))
|
||||
try:
|
||||
raw = await asyncio.wait_for(
|
||||
|
|
|
|||
|
|
@ -62,6 +62,22 @@ class IamClient(RequestResponse):
|
|||
)
|
||||
return resp.user
|
||||
|
||||
async def authenticate_anonymous(self, timeout=IAM_TIMEOUT):
|
||||
"""Request anonymous access from the IAM regime.
|
||||
|
||||
Returns ``(user_id, workspace, roles)`` if the regime permits
|
||||
anonymous access, or raises ``RuntimeError`` with error type
|
||||
``auth-failed`` if it does not."""
|
||||
resp = await self._request(
|
||||
operation="authenticate-anonymous",
|
||||
timeout=timeout,
|
||||
)
|
||||
return (
|
||||
resp.resolved_user_id,
|
||||
resp.resolved_workspace,
|
||||
list(resp.resolved_roles),
|
||||
)
|
||||
|
||||
async def resolve_api_key(self, api_key, timeout=IAM_TIMEOUT):
|
||||
"""Resolve a plaintext API key to its identity triple.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue