# Auth (login / identity / authorization)

First normalized component. **Goal: path to shared code** — converge the three sister
projects onto a common identity + API-key contract, proposed as the `ZB.MOM.WW.Auth`
library set, while each project keeps its own authorization vocabulary.

- The one target: [`spec/SPEC.md`](spec/SPEC.md)
- The proposed shared library: [`shared-contract/ZB.MOM.WW.Auth.md`](shared-contract/ZB.MOM.WW.Auth.md)
- Divergences + backlog: [`GAPS.md`](GAPS.md)
- Current state, per project: [`current-state/`](current-state/)

## Why auth is a strong first candidate

All three projects authenticate humans via **LDAP** (GLAuth in dev), do **bind-then-search**,
read groups from **`memberOf`**, use a **service account**, support **TLS/StartTLS** with an
`AllowInsecureLdap` dev escape hatch, and **never log secrets**. Two of three implement an
almost identical **peppered HMAC-SHA256 API-key** scheme with constant-time comparison. That
common core is re-implemented per repo and has already drifted (config key names, dev base DN,
cookie names). Authorization, by contrast, is genuinely domain-specific and is **not** unified.

## Status by project

| Project | AuthN today | Machine auth | AuthZ model (stays per-project) | Sessions | Adoption status |
|---|---|---|---|---|---|
| **OtOpcUa** | LDAP (GLAuth) via OPC UA UserName token; X.509 + anonymous also | — (OPC UA transport security) | `NodePermissions` bitmask (data-plane ACL trie) + `AdminRole` (control-plane) | Per-session `UserAuthorizationState`, 5-min freshness / 15-min staleness, generation-bound | Not started |
| **MxAccessGateway** | LDAP (GLAuth) for **dashboard** | **API keys** (`mxgw_…`, SQLite, peppered HMAC, scopes + constraints) | gRPC **scopes** (`session:*`/`invoke:*`/`events:*`/`metadata:*`/`admin`) + dashboard `Admin`/`Viewer` | Dashboard cookie (8h sliding) + 30-min Data-Protection hub bearer | Not started |
| **ScadaBridge** | LDAP for UI/CLI/Management API (Basic→LDAP) | **API keys** (`X-API-Key`, peppered HMAC, per-method approval) — Inbound API only | Roles `Admin`/`Design`/`Deployment`/`Audit`/`AuditReadOnly` + **site-scoping** | Cookie (`…ScadaBridge.Auth`, 30-min idle) + 15-min refresh JWT for programmatic | Not started |

See each project's [`current-state/<project>/CURRENT-STATE.md`](current-state/) for the
code-verified detail and its adoption plan.

## Normalized vs. left per-project

**Normalized (the shared target):** LDAP/identity config schema + canonical key names;
bind-then-search behavior incl. DN/filter escaping and timeouts; a generic group→role
mapping seam; **the standardized canonical role set every project maps onto
([`spec/CANONICAL-ROLES.md`](spec/CANONICAL-ROLES.md))**; the API-key contract (token format,
peppered HMAC-SHA256, constant-time compare, audit); cookie/claim conventions; dev-bypass
flag conventions; secret handling.

**Left per-project (native enforcement, mapped onto the canonical roles):** the authorization
*enforcement* vocabularies (`NodePermissions` / gRPC scopes / app roles + site-scoping), OPC UA
transport security, OtOpcUa's generation/staleness session model, ScadaBridge's site-scope rules.
