elsa-core/specs/012-external-authentication/spec.md
2026-08-02 03:35:39 +02:00

43 KiB

Feature Specification: External Authentication

Feature Branch: codex/012-external-authentication

Created: 2026-07-24

Status: Approved — revised 2026-07-24

Input: Deliver Elsa 3 external authentication and Identity Provider Connections end to end across Elsa Core and Elsa Studio, based on the approved PRD, domain language, and architecture decisions.

Product Context

Elsa supports local credentials, Elsa-issued tokens, API keys, and a startup-configured direct OpenID Connect option in Studio. It does not provide a server-owned broker where deployers and authorized administrators can compose multiple external authentication choices, manage selected connections at runtime, link external identities to Elsa Users, and preserve Elsa authorization.

This feature adds External Authentication as an Elsa capability. An Identity Provider Connection describes Elsa's trust relationship with an external provider. Connections can be deployment-owned configuration, administrator-owned persisted data, or explicit persisted Studio Overrides. Elsa Server brokers sign-in and issues Elsa credentials; Studio discovers Login Methods and supplies management experiences without receiving provider secrets.

OpenID Connect is the first adapter. The connection and extension contracts must also support future provider-specific OAuth adapters without changing the core connection model or client completion flow.

Clarifications

Session 2026-07-24

  • Elsa Server owns provider redirects, callbacks, identity resolution, permission resolution, and Elsa credential issuance.
  • Configuration provides the baseline; an explicit complete Studio Override shadows the same immutable Connection Key without field merging. Disabled overrides keep shadowing; archived overrides reveal configuration.
  • A connection uses a protocol-neutral envelope with adapter-owned, versioned settings and non-secret Secret Bindings.
  • SSO administration is host-wide within the currently connected Elsa server environment; v1 has no persisted/editable environment target field.
  • External identities link to Elsa Users by immutable Connection Key, validated issuer namespace, and stable subject—never by email or user name by default.
  • Unknown identities are governed by a deployer-controlled, extensible Unlinked Identity Policy; the safe default rejects them.
  • The matcher-based Unlinked Identity Policy may use one deployed IExternalUserMatcher to propose an existing user. defaultRoleIds are static and apply only when a new user is created.
  • Local Elsa credentials and enabled external connections are unified as Login Methods, but local login is not modeled as an Identity Provider Connection.
  • Both Studio Server and Studio WebAssembly use the broker completion-code flow with host-appropriate session handling.
  • Existing direct Studio OpenID Connect remains a selectable compatible mode throughout Elsa 3.x; brokered mode is recommended and staged deprecation cannot remove Direct OIDC before a future major release.
  • Connection testing is on demand. Continuous health monitoring and history are outside v1.
  • Security events are published for audit subscribers; this feature does not own an audit database.
  • The OIDC adapter uses an exact discoveryUrl, a deployment-derived callback, confidential-client authorization code with S256 PKCE, and client_secret_basic or client_secret_post.
  • Login and logout are Elsa-initiated. Upstream tokens are discarded except for the minimum protected artifact required by configured upstream logout.

User Scenarios & Testing (mandatory)

User Story 1 - Sign In Through an External Provider (Priority: P1)

An Elsa user selects an enabled external Login Method, authenticates with the provider, and returns to Studio with an Elsa session containing the permissions Elsa grants to the linked user.

Why this priority: Brokered sign-in is the core user value and the foundation for all management and extension work.

Independent Test: Configure one OpenID Connect connection through deployment configuration, discover it from Studio, complete sign-in, and verify the resulting Elsa principal is tenant-scoped and contains Elsa-issued permissions without exposing provider or Elsa tokens in redirects.

Acceptance Scenarios:

  1. Given an enabled, valid connection and a linked identity, When a user completes provider authentication, Then Elsa resolves the link and returns a short-lived, single-use completion code to the registered client.
  2. Given an unknown identity and the reject policy, When provider authentication succeeds, Then Elsa denies access with a safe error and correlation identifier.
  3. Given an unknown identity and an allowed just-in-time policy, When provider authentication succeeds, Then Elsa creates a credential-less Elsa User, publishes one durable identity link, compensates a failed publication, and issues no credentials until both records exist.
  4. Given a connection changes materially after initiation, When its callback arrives, Then Elsa rejects the flow rather than completing against the new settings.
  5. Given two callbacks for the same previously unknown External Identity arrive concurrently, When JIT provisioning runs, Then both converge on one tenant-scoped link and Elsa User or one safely retries after observing the winning transaction.

User Story 2 - Manage Persisted Connections (Priority: P1)

An authorized connection administrator creates, reads, updates, enables, disables, archives, restores, tests, and previews database-owned Identity Provider Connections from Elsa Studio. Deployment-owned connections appear in the same list but remain read-only.

Why this priority: Runtime administration without restart is the main capability beyond existing direct OpenID Connect configuration.

Independent Test: Create a disabled OpenID Connect draft in Studio, supply settings and Secret Bindings, run test and preview, enable it, and verify it becomes discoverable across the cluster without restart.

Acceptance Scenarios:

  1. Given an installed adapter, When an administrator creates a disabled draft, Then Studio renders its settings from the adapter description and permits incomplete draft storage.
  2. Given a valid draft with resolvable required secrets, When it is enabled, Then it becomes an effective Login Method without restart.
  3. Given a configuration-owned connection, When any runtime caller attempts to mutate it, Then Elsa rejects the operation.
  4. Given two administrators edit one persisted connection, When the second submits a stale revision, Then Elsa reports a concurrency conflict without overwriting the first update.
  5. Given configuration owns a key, When an administrator explicitly creates a Studio Override, Then the complete override shadows configuration without field merging.
  6. Given that override is disabled or archived, When the registry resolves, Then disabled continues shadowing while archived deliberately reveals the configuration baseline.

User Story 3 - Preserve Elsa Authorization (Priority: P1)

A security administrator links external identities to Elsa Users and configures privilege-safe role provisioning for JIT users. Elsa Roles remain the only path to Elsa permission claims.

Why this priority: External authentication must not bypass Elsa-specific roles and permissions.

Independent Test: Configure the matcher-based policy with one test matcher and a create-user fallback, then verify a single match links without role changes, no-match creates with static authorized defaultRoleIds, and ambiguous/error rejects.

Acceptance Scenarios:

  1. Given one matcher returns one existing user, When policy evaluation completes, Then Elsa links that user without changing roles.
  2. Given no matcher result, When fallback is Reject or CreateUser, Then Elsa applies that action; CreateUser assigns only static authorized defaultRoleIds.
  3. Given ambiguous matcher results or a matcher error, When policy evaluation completes, Then Elsa rejects authentication safely.
  4. Given matcher-required claims, When matching completes, Then those claims are discarded and never persisted.
  5. Given a Role is referenced by a database- or configuration-owned CreateUser path, When ordinary Role deletion is attempted, Then Elsa blocks deletion and returns safe dependency diagnostics.
  6. Given a configuration-owned reference, When deletion impact is inspected or remediation is requested, Then the sanitized configuration path is returned and deployment configuration is not mutated.
  7. Given only editable database references and an authorized actor, When remediation is confirmed, Then Elsa removes the Role from every JIT policy before deleting it; an incomplete best-effort run leaves the Role intact and is safely retryable.

User Story 4 - Use the Same Broker from Studio Server and WebAssembly (Priority: P1)

Studio Server and Studio WebAssembly use the same Login Method discovery and broker completion model while applying the session protections appropriate to confidential server and public browser clients.

Why this priority: Both supported Studio hosting models must remain first-class.

Independent Test: Complete the same configured external sign-in from both hosts and verify exact callback matching, mandatory client-to-Elsa PKCE, correct session establishment, refresh handling, and logout.

Acceptance Scenarios:

  1. Given a Studio Server client, When code exchange succeeds, Then the host retains Elsa refresh credentials server-side and the browser receives only a secure, HTTP-only Studio session.
  2. Given a Studio WebAssembly client, When code exchange succeeds, Then no client secret is accepted and exact-origin cross-origin policy plus PKCE are enforced.
  3. Given an absolute or protocol-relative return target, When login, recovery, preview, or logout validates it, Then the target is rejected.
  4. Given both Direct OpenID Connect and Brokered External Authentication are selected, When Studio starts, Then startup fails with an actionable configuration error.
  5. Given an existing client calls the current local login and refresh endpoints, When the broker feature is installed, Then their token-returning contract remains unchanged unless the client explicitly adopts the new broker-local completion route.

User Story 5 - Operate Connections Safely (Priority: P2)

An operator can distinguish administrative enablement, structural validity, and the most recent on-demand test result, diagnose failures using safe correlation identifiers, and recover without depending on the connection being repaired.

Why this priority: Provider failure must be diagnosable without leaking secrets or locking administrators out.

Independent Test: Test a valid but unreachable connection, verify it stays administratively enabled, inspect the redacted result, then sign in through the independent recovery method and repair it.

Acceptance Scenarios:

  1. Given a provider test fails, When Studio refreshes the connection, Then enabled intent is unchanged and the result is labeled with tested revision and timestamp.
  2. Given a connection is materially updated, When Studio displays an older test result, Then it is marked stale.
  3. Given final-login-path protection is active, When an administrator tries to disable the final valid method without recovery or privileged override, Then Elsa rejects the operation.
  4. Given an external provider is unavailable, When an authorized operator uses an independent local or break-glass method, Then connection management remains reachable.

User Story 6 - Extend Providers and Policies (Priority: P2)

A module author deploys a trusted Protocol Adapter, Unlinked Identity Policy, or External User Matcher. The server publishes its settings description so a standard Studio form works without provider-specific database columns or Studio code; an optional custom editor can improve the experience.

Why this priority: The initial OpenID Connect implementation must not prevent later GitHub or other provider-specific adapters.

Independent Test: Register a conformance adapter with unique settings and a secret field, configure it using the generic editor, authenticate a normalized identity, and complete the unchanged broker flow.

Acceptance Scenarios:

  1. Given an installed adapter with described settings, When an administrator creates a connection, Then Studio renders and validates its common and adapter-specific fields.
  2. Given the adapter has no custom Studio editor, When it is configured, Then the generic editor remains fully functional.
  3. Given an adapter settings schema evolves, When an older persisted version loads, Then the adapter provides a compatible migration or a clear invalid state without corrupting the record.
  4. Given a new adapter is installed, When it authenticates successfully, Then it produces the same protocol-neutral External Identity consumed by the broker.

User Story 7 - Administer External Identity Links (Priority: P2)

An authorized security administrator searches tenant-scoped Elsa Users, prelinks a known external subject, inspects safe link metadata, or unlinks it with confirmation.

Why this priority: Preprovisioned-only environments need deliberate admission without full user and role management in this feature.

Independent Test: Find a user through the bounded picker, prelink a connection/issuer/subject tuple, complete external sign-in, unlink it, and verify subsequent sign-in follows the configured unlinked policy.

Acceptance Scenarios:

  1. Given a tenant context and read permission, When the administrator searches users, Then only paginated minimal selection data for that tenant is returned.
  2. Given a valid external identity tuple, When the administrator prelinks it to a user, Then the next matching sign-in resolves that user.
  3. Given a link is removed, When the identity signs in again, Then Elsa applies the effective Unlinked Identity Policy.
  4. Given a caller lacks identity-link permission, When they access the page or API, Then both route and operation authorization reject access regardless of menu visibility.
  5. Given a selected Elsa User belongs to another tenant, When an administrator attempts to prelink it, Then Elsa rejects the link without revealing cross-tenant user details.
  6. Given the external identity tuple is already linked, When another prelink or JIT operation targets a different user, Then the durable uniqueness rule rejects it.

User Story 8 - Migrate Existing Direct OpenID Connect Deployments (Priority: P3)

A deployment owner can keep the current direct Studio OpenID Connect mode or deliberately migrate its settings to one configuration-owned broker connection without silent secret movement.

Why this priority: Adoption must not break existing Elsa 3 deployments.

Independent Test: Start Studio in Direct OpenID Connect mode after installing the feature, verify behavior is unchanged, then follow the migration guide and explicitly switch to brokered mode.

Acceptance Scenarios:

  1. Given an existing direct deployment that has not selected brokered mode, When the new modules are installed, Then existing authentication remains unchanged.
  2. Given a deployment follows the migration guide, When it creates the equivalent configuration-owned connection and explicitly changes mode, Then the brokered chooser replaces direct authentication.
  3. Given migration is rolled back, When Direct OpenID Connect is selected again, Then its original settings remain usable.

Edge Cases

  • Anonymous discovery occurs without a trusted tenant context.
  • A non-host connection scope is rejected; identity-provider connection keys are host-wide in v1.
  • Configuration shadows a previously enabled persisted connection.
  • A callback or refresh reaches a different Elsa node than initiation.
  • A connection is disabled, archived, materially updated, or has its secret rotated during sign-in.
  • A disabled draft is incomplete or references a missing secret.
  • A provider is structurally valid but unreachable.
  • An OIDC discovery endpoint resolves to a private, loopback, link-local, reserved, redirected, or oversized response.
  • An administrator loses their Studio session during Preview Sign-in.
  • A credential-less Elsa User attempts local login.
  • JIT provisioning races for the same external identity or generated user name.
  • An external subject signs in to two target tenants.
  • A provider changes mutable email, display name, or group claims.
  • A selected matcher extension is unavailable, returns multiple candidates, or throws an error.
  • A connection is archived and later restored, or a new connection reuses its former display key.
  • Automatic redirect fails and must return to the chooser without looping.
  • The provider does not support upstream logout or its logout endpoint fails.
  • Access tokens issued before disablement remain valid until their short expiry unless explicitly revoked.
  • Management UI is visible to a user who may read but not test, preview, edit, or delegate permissions.
  • A remote or malicious icon/display name attempts to spoof the login chooser.

Requirements (mandatory)

Functional Requirements

Connection Registry and Ownership

  • FR-001: Elsa MUST expose External Authentication independently of any Studio host.
  • FR-002: Elsa MUST present one effective registry composed from configuration-owned and optional database-owned Identity Provider Connections.
  • FR-003: Configuration-owned connections MUST be inspectable but immutable through runtime management surfaces.
  • FR-004: Database-owned connections MUST support create, read, update, enable, disable, archive, restore, test, and Preview Sign-in operations.
  • FR-005: Creating or changing a database-owned connection for an installed adapter MUST take effect without server restart.
  • FR-006: Configuration MUST provide the baseline for a host-wide Connection Key; only an explicit Studio Override may shadow it.
  • FR-007: A Studio Override MUST replace the complete connection document. Disabled overrides continue shadowing; archived overrides reveal configuration; restoring resumes the shadow.
  • FR-008: Every connection MUST have a stable record ID for management/transient broker state and an immutable logical Connection Key for durable links and long-lived sessions.
  • FR-009: SSO connection administration MUST be host-wide within the currently connected Elsa server environment. V1 MUST NOT persist or expose an editable Deployment Target/Server Environment field.
  • FR-010: Creating a Studio-owned record for a configuration key MUST require the explicit override operation; ordinary duplicate keys are rejected.
  • FR-011: Archive/restore MUST preserve the Connection Key and links. Archiving an override reveals its configuration baseline; archiving an ordinary Studio connection removes it from the effective registry.
  • FR-012: Database mutations MUST enforce optimistic concurrency.
  • FR-013: Enabled intent, structural validity, and observed test result MUST remain separate states.
  • FR-014: Incomplete disabled drafts MAY be saved; enabling MUST require valid settings and resolvable required secrets.
  • FR-015: Provider test failure MUST NOT automatically disable or hide a valid enabled connection.
  • FR-016: Anonymous discovery MUST return host-wide methods only in v1 and reveal no tenant existence.

Extensibility, Settings, and Secrets

  • FR-017: Protocol Adapters, Unlinked Identity Policies, and External User Matchers MUST be trusted deployed extensions registered at startup. Runtime configuration MAY select only installed, deployment-allowed types.
  • FR-018: Each extension type MUST expose a stable identifier and descriptor containing its settings schema version, fields, validation rules, UI hints, secret-binding metadata, conditional visibility, capabilities, presentation, and optional custom-editor contract key/version.
  • FR-019: Studio MAY use a custom editor registered for an extension type, but absence of one MUST NOT prevent complete configuration.
  • FR-020: Connections MUST use a protocol-neutral envelope with opaque, versioned adapter settings whose compatibility and migration are owned by the adapter.
  • FR-021: Adapter-specific fields MUST NOT require provider-specific connection columns or tables.
  • FR-022: Successful adapters MUST return a normalized External Identity containing a validated issuer namespace, stable subject, and bounded claims.
  • FR-023: V1 MUST include a conforming OpenID Connect adapter.
  • FR-024: The OpenID Connect adapter MUST use one exact absolute HTTPS discoveryUrl, a deployment-derived callback, a confidential upstream client, authorization-code flow, mandatory S256 PKCE, and client_secret_basic or client_secret_post; it MUST validate state, correlation, nonce, signature, issuer, audience/authorized party, expiry, and callback errors.
  • FR-025: Future provider-specific OAuth or SAML adapters MUST be addable without changing the connection envelope or client completion contract.
  • FR-026: Sensitive settings MUST use Secret Bindings rather than stored secret values.
  • FR-027: Secret Bindings MUST distinguish Managed and External ownership. Managed Secrets integrate with Elsa Secrets; a built-in configuration-key resolver MUST support External Secrets from standard .NET configuration.
  • FR-028: Management and diagnostic surfaces MUST expose only secret configured state and support replacement or removal without reveal.
  • FR-029: Exact discoveryUrl and its derived issuer/endpoints/keys MUST be the safe default. Advanced settings MAY override discovery-derived issuer, authorization/token endpoints, and signing keys when deployment policy permits.
  • FR-030: Advanced trust overrides MUST require the unsafe-provider-trust permission, explicit confirmation, persistent warnings, and a redacted security notification.
  • FR-031: Connection administrators MUST NOT weaken Elsa-owned Broker Security Invariants: callback derivation, confidential-client requirement, S256 PKCE, state/correlation/nonce, signature validation, audience/lifetime validation, one-time codes, and secret redaction remain mandatory.

Broker, Clients, and Sessions

  • FR-032: Elsa Server MUST own provider redirects, callbacks, account resolution, permission resolution, and Elsa credential issuance.
  • FR-033: Provider tokens, Elsa tokens, and secrets MUST NOT appear in redirect URLs.
  • FR-034: Successful local and external authentication MUST complete with a short-lived, single-use Elsa authorization code.
  • FR-035: The completion code MUST be bound to an Authentication Client, exact callback URI, target tenant, and PKCE challenge.
  • FR-036: Authentication Clients MUST be distinct from Elsa API Applications, grant no permissions, and be deployment-managed in v1.
  • FR-037: Broker state MUST bind target tenant, connection record ID, and material connection revision.
  • FR-038: Callback, code exchange, and external refresh MUST reject disabled, archived, or materially changed connections using authoritative current state.
  • FR-039: Material revision MUST cover adapter settings, secret binding identity/generation, Unlinked Identity Policy/matcher settings, static defaultRoleIds, and override lifecycle; presentation-only changes MAY avoid invalidating a flow.
  • FR-040: Correlation state, completion codes, and connection checks MUST work when requests cross Elsa nodes.
  • FR-041: Anonymous discovery and initiation MUST verify the shared effective-registry version before returning or redirecting, so a completed database mutation cannot remain stale indefinitely on another node.
  • FR-042: External Authentication Sessions MUST retain only bounded normalized identity/role provenance and enforce a configurable maximum age.
  • FR-043: External refresh credentials MUST identify their External Authentication Session and check connection state, maximum age, and revocation.
  • FR-044: External refresh MUST reevaluate current Elsa-owned user and role grants without re-querying upstream claims.
  • FR-045: Existing local refresh behavior MUST remain distinguishable and compatible.
  • FR-046: Disabling or archiving a connection MUST stop initiation, in-flight callback, and refresh; existing short-lived access tokens remain valid until expiry unless explicitly revoked.
  • FR-047: Normal logout MUST end the Elsa session.
  • FR-048: Connections that support Upstream Logout MUST offer Disabled, UserChoice, and Always modes, defaulting to Disabled.
  • FR-048A: Login and logout MUST be Elsa-initiated in v1. IdP-initiated login and provider-initiated front-channel/back-channel logout are out of scope.
  • FR-048B: Provider access/refresh tokens MUST be discarded after callback and optional user-info use. Only the minimum protected upstream artifact required for configured logout MAY be retained, and never beyond the external session.
  • FR-049: Successful external authentication MUST resolve to an Elsa User before Elsa credentials are issued.
  • FR-050: External Identity Links MUST be separate from users and keyed by target tenant, immutable Connection Key, validated issuer namespace, and stable subject.
  • FR-051: Built-in behavior MUST NOT link by email, user name, or another mutable profile attribute.
  • FR-052: One Elsa User MAY have multiple links and MAY exist without Local Credentials.
  • FR-053: Credential-less users MUST contain no placeholder password material and local login MUST fail with the same public result as other invalid credentials.
  • FR-054: JIT provisioning MUST use a convergent create-link-or-get-existing contract that retries generated-name collisions, compensates losing/failed link writers, and never makes mutable provider attributes identity keys.
  • FR-055: The External Identity Link tuple (target tenant, connectionKey, issuer namespace, subject) MUST have durable uniqueness. Concurrent JIT or prelink operations for the same tuple MUST converge on one link/user.
  • FR-056: JIT-created users MUST belong to the broker-resolved target tenant. Host-wide connection deployment does not remove Elsa User tenancy.
  • FR-057: The safe default Unlinked Identity Policy MUST reject access; v1 MUST also include an explicitly selectable JIT creation policy.
  • FR-058: Each connection MUST select an Unlinked Identity Policy. Deployment configuration controls the default and allowed policy/matcher types.
  • FR-058A: The matcher-based policy MUST select exactly one IExternalUserMatcher, pass only its declared required claims ephemerally, and accept only one unambiguous existing-user result.
  • FR-058B: No match MUST follow configured Reject or CreateUser fallback. Ambiguous results and errors MUST reject. V1 MUST NOT ship an Elsa first-party verified-email matcher.
  • FR-059: V1 MUST support administrator prelinking and unlinking but MUST NOT include end-user self-service linking.
  • FR-060: Elsa MUST remain authoritative for permission claims and MUST expand them only through Elsa Roles.
  • FR-061: Each connection MAY define static defaultRoleIds used only when CreateUser creates a new user, including a matcher policy's create-user no-match fallback.
  • FR-062: External User Matchers MUST NOT select or mutate roles or permissions.
  • FR-063: Saving defaultRoleIds MUST verify that the actor may assign every selected Role. CreateUser MUST atomically assign those authorized roles.
  • FR-063A: Elsa Role deletion MUST query extensible dependency contributors and block while any database- or configuration-owned CreateUser or matcher no-match CreateUser defaultRoleIds reference remains, including disabled, archived, shadowed, and ineffective definitions.
  • FR-063B: Configuration-owned references MUST return a sanitized configuration path and policy branch and MUST NOT be auto-mutated.
  • FR-063C: An authorized, prevalidated remediation command MUST remove the Role from every editable database-owned JIT policy and delete it only after a current dependency inspection reports no references.
  • FR-063D: Remediation MUST be atomic when stores share a transaction. A best-effort implementation MUST prevalidate all permissions/revisions, remove references before deletion, leave the Role intact after incomplete removal, return partial-progress diagnostics, and be safely retryable.
  • FR-063E: Removal that empties defaultRoleIds for any CreateUser path MUST produce a warning and require explicit confirmation. Dependency-version or connection-revision conflicts MUST prevent Role deletion.
  • FR-063F: Full Roles UI remains out of scope. The backend contract MAY be integrated into a future Elsa Roles UI but MUST NOT create another External Authentication Settings page.
  • FR-064: Matched/existing users retain Elsa-managed roles. V1 Studio MUST NOT expose claim/group-to-permission, wildcard, pass-through, or claim-to-role mapping UI.
  • FR-065: Complete external claim sets and upstream access/refresh tokens MUST NOT be persisted. Minimal protected upstream logout material is the only exception.

Login Discovery and Studio

  • FR-066: Login Method discovery MUST unify local Elsa credentials and external connections without modeling local login as a connection.
  • FR-067: Anonymous discovery MUST return only method key, kind, display name, trusted icon ID, display order, preferred state, and Elsa-owned initiation URL. It MUST NOT return adapter settings, provider authority, upstream client ID, health, secrets, or remote icons.
  • FR-068: Studio MUST always show an accessible chooser.
  • FR-069: A preferred enabled method MAY be ordered and emphasized but MUST NOT trigger automatic redirect.
  • FR-070: Local Login Method availability and preferred selection MUST be deployment-controlled for the host target.
  • FR-071: At most one preferred external method may be effective. If unavailable, the chooser remains usable and shows safe status.
  • FR-072: Local credential authentication MUST use the same client-, callback-, tenant-, and PKCE-bound completion contract as external authentication.
  • FR-073: Brokered local credential completion MUST use a new opt-in broker endpoint. The existing token-returning local login and refresh endpoints MUST retain their public contract for existing API clients.
  • FR-074: Studio Server MUST act as a confidential Authentication Client, exchange the code on the host, retain refresh credentials server-side, and establish a secure HTTP-only browser session.
  • FR-075: Studio WebAssembly MUST act as a public Authentication Client with no client secret and mandatory PKCE. Code exchange MUST return an Elsa access token and rotating, reuse-detecting external-session refresh token only to an exactly registered origin; wildcard origins and credentialed cross-origin requests are forbidden.
  • FR-076: The default WebAssembly token accessor MUST keep post-exchange credentials in memory so reload, a new tab, or a closed tab requires sign-in. Tab-scoped session storage and durable browser storage MAY be explicit deployment choices; every persistent browser policy MUST carry a security warning.
  • FR-077: Every callback and logout URI MUST match an exact client registration.
  • FR-078: Every user-controlled post-authentication target MUST be an allowlisted client-local path; absolute, protocol-relative, and unregistered targets MUST be rejected.
  • FR-079: Studio MUST label the connection's Upstream Client Registration separately from the deployment-owned Elsa Authentication Client.
  • FR-080: Studio MUST place SSO Connections at one-level Settings → SSO (/settings/sso-connections) and place External Identity Links and External Authentication Sessions as separate Security pages.
  • FR-081: Link administration MUST use a permission-guarded, tenant-scoped, paginated user lookup returning only minimal selection data.
  • FR-082: Management APIs and Studio routes MUST enforce operation authorization independently of menu visibility.
  • FR-083: Studio MUST explain source ownership, shadowing, archive, validity, enabled intent, and stale test results while showing only caller-allowed actions.
  • FR-084: Login buttons MUST be text-first, keyboard and screen-reader accessible, deterministically ordered, and limited to trusted server-hosted presentation assets with safe fallback.
  • FR-084A: Elsa.Studio.Authentication.UI MUST own the generic login/logout shell and contribution contracts. Settings is UI composition/navigation only and introduces no server-side Settings persistence model.

Security, Operations, and Recovery

  • FR-085: Management operations MUST use distinct permissions for read, create, update/override, archive/restore, test, preview, unsafe provider-trust overrides, policy/role provisioning, link management, and session revocation.
  • FR-086: Preview Sign-in MUST use separate short-lived, one-time state and result records bound to administrator, connection record ID, draft revision, and preview callback.
  • FR-087: Preview MUST NOT create or link a user, issue a normal code or credential, or open a normal session.
  • FR-088: Only the initiating authorized administrator with an active Studio session MAY read the one-time, allowlisted, redacted preview result.
  • FR-089: On-demand tests MUST record tested revision and timestamp and become stale after material change; v1 MUST NOT require polling or health history.
  • FR-090: The latest redacted on-demand test result MUST be stored in a shared observation store keyed by Connection ID and tested revision so every node can return the same latest observation. A material revision change MUST make it stale; historical observations need not be retained.
  • FR-091: Elsa SHOULD expose the same test contract as a separately tagged, opt-in application health check that does not affect readiness by default.
  • FR-092: Outbound provider traffic MUST apply deployment egress controls, HTTPS by default, bounded time and response size, controlled redirects, resolved-address checks, and safe exception handling.
  • FR-093: Deployment policy MUST be able to deny private, loopback, link-local, reserved, or unapproved destinations and use an approved proxy.
  • FR-094: Public broker errors MUST use documented safe categories and correlation identifiers without distinguishing unknown users from missing links.
  • FR-095: Anonymous discovery, initiation, callback, and exchange MUST be rate-limited; state and codes MUST expire and be single-use.
  • FR-096: Secrets, tokens, unrestricted claims, and provider response bodies MUST NOT appear in responses, redirects, logs, tests, preview, health details, or security notifications.
  • FR-097: Each connection MUST define a normalized-claim projection that allowlists claims required by the selected user matcher and preview, applies bounded limits, and discards matcher-required claims after policy evaluation.
  • FR-098: Every Secret Binding resolution MUST produce an opaque, nonreversible generation fingerprint. A changed fingerprint is a material revision and MUST reject an in-flight callback; the fingerprint MUST never be exposed through management or diagnostic surfaces.
  • FR-099: Rate-limit partition keys, thresholds, and retry behavior, plus outbound timeout, redirect, response-size, DNS/rebinding, proxy, and destination defaults MUST be deployment-configurable with secure documented defaults and a conformance test matrix.
  • FR-100: Elsa MUST publish typed, immutable, redacted security notifications for sign-in outcomes and privileged connection, policy, secret, test, preview, link, and session operations.
  • FR-101: This feature MUST NOT require an audit store; durable history is owned by an optional subscriber.
  • FR-102: A configurable final-login-path guard MUST prevent lockout unless an independent deployment-owned Break-glass Authentication method or explicitly privileged confirmed override exists.
  • FR-103: Break-glass Authentication MUST remain outside normal Login Method discovery and keep management reachable without the connection being repaired.

Compatibility and Delivery

  • FR-104: Existing direct Studio OpenID Connect MUST remain supported as a deployment-selected mode throughout Elsa 3.x.
  • FR-105: Direct OpenID Connect and Brokered External Authentication MUST be mutually exclusive for one Studio host; ambiguous configuration MUST fail startup.
  • FR-106: Migration guidance MUST map direct settings to a configuration-owned broker connection without silently moving secrets or changing mode.
  • FR-107: V1 MUST support both Studio Server and Studio WebAssembly and deliver the paired Studio modules with the Core/server capability.
  • FR-108: V1 MUST include configuration-first broker operation, optional persisted administration, and the enterprise security controls defined in this specification.
  • FR-109: Brokered mode is recommended for multiple/runtime-managed providers. Direct OIDC deprecation MAY begin only after parity and migration tooling; removal requires a future major release and advance notice.

Key Entities

  • Identity Provider Connection: Elsa's host-wide trust relationship with an external provider, with a stable management record ID, immutable logical Connection Key, source/override provenance, adapter selection, presentation, lifecycle, revision, settings, Secret Bindings, policy, and static create-user roles.
  • Protocol Adapter Description: Safe metadata describing an installed adapter's settings, validation, secrets, capabilities, presentation, and schema version.
  • External Identity: A normalized provider assertion identified by validated issuer namespace and stable subject.
  • External Identity Link: A tenant-scoped association from Connection Key/issuer/subject to the Elsa User that owns Elsa authorization.
  • Elsa User: Elsa's authorization account, optionally possessing Local Credentials and potentially linked to multiple external identities.
  • Unlinked Identity Policy Selection: The effective policy and settings used when an authenticated identity has no link.
  • External User Matcher Selection: One matcher configured by the matcher-based Unlinked Identity Policy, with versioned settings, declared ephemeral required claims, and Reject/CreateUser no-match fallback.
  • Authentication Client: A deployment-owned Elsa client registration with client type, exact callbacks, PKCE requirement, and optional logout callbacks.
  • External Authentication Session: A bounded session linking user, Connection Key, minimal identity/role provenance, optional protected logout artifact, maximum age, refresh eligibility, and revocation state.
  • Secret Binding: A Managed or External non-secret resolver reference with configured/resolvable state.
  • Connection Test Result: A redacted observation bound to connection revision and timestamp, distinct from enablement and validity.
  • Preview Result: A short-lived, one-time, administrator-bound redacted identity and authorization projection that cannot become a normal session.

Success Criteria (mandatory)

Measurable Outcomes

  • SC-001: An integrator can configure one OpenID Connect connection entirely through deployment configuration and complete external sign-in from both supported Studio hosts.
  • SC-002: An authorized administrator can create and enable a persisted connection without restarting any Elsa node.
  • SC-003: A conformance adapter with unique settings can be configured through the generic Studio editor without database schema changes or adapter-specific Studio code.
  • SC-004: Automated contract tests find zero provider tokens, Elsa tokens, secret values, unrestricted claims, or provider response bodies in management, discovery, redirect, error, test, preview, health, log, and notification outputs.
  • SC-005: Tenant-isolation tests show that discovery and links never reveal or resolve another tenant's scoped connection or user.
  • SC-006: Multi-node tests complete initiation, callback, and code exchange on different nodes while preserving single-use and current-revision checks.
  • SC-007: Disabling, archiving, materially changing, or revoking an external session prevents callback or refresh before any new Elsa credential is issued.
  • SC-008: Admission tests prove single-match/no-match/ambiguous/error behavior, ephemeral matcher claims, static create-user role authorization, and no role mutation for matched users.
  • SC-009: Credential-less users can authenticate externally, contain no placeholder password material, and receive indistinguishable local-login failure.
  • SC-010: Preview tests prove no user, link, normal completion code, Elsa credential, or normal session is created.
  • SC-011: Open-redirect, replay, tenant-enumeration, and outbound-request security tests reject all documented malicious cases.
  • SC-012: Configuration/database collision and optimistic-concurrency tests produce deterministic, visible outcomes without silent overwrite.
  • SC-013: Existing Direct OpenID Connect deployments continue unchanged until an explicit, validated mode switch.
  • SC-014: Every privileged operation and sign-in outcome publishes a redacted security notification consumable by an audit subscriber.
  • SC-015: The chooser and management paths pass automated keyboard, screen-reader semantics, trusted-asset, preferred-ordering, and no-auto-redirect checks.
  • SC-016: Role-lifecycle tests enumerate database/configuration references across all lifecycle states, block ordinary deletion, preserve configuration, require empty-role warnings, and prove atomic or safely retryable best-effort remediation never deletes a still-referenced Role.

Assumptions

  • The existing Elsa Identity user, role, permission claim, and token facilities remain the authorization foundation.
  • The Elsa User credential model will be migrated compatibly to permit users without Local Credentials.
  • Elsa Secrets or an equivalent resolver can provide writable secrets for persisted connections.
  • Deployments that require cross-node sign-in provide shared protected state and compatible data-protection configuration.
  • Authentication Clients, default/allowed policies, allowed adapters/matchers, role-assignment boundaries, external base address, break-glass methods, and Studio authentication mode remain deployment-controlled in v1.
  • Database persistence for connection data is optional; configuration-first operation is a complete supported deployment.
  • OpenID Connect is the only provider protocol delivered in v1; provider-specific OAuth and SAML adapters are extension follow-ups.
  • Tenant-targeted connections, full user/role administration, end-user self-linking, claim-permission mapping UI, IdP-initiated flows, continuous provider monitoring, audit persistence, general provider-token retention, and connection import/export remain outside this feature.